mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
feat: wip estimate send mail
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
import React, { createContext, useContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import { Spinner } from '@blueprintjs/core';
|
import { Spinner } from '@blueprintjs/core';
|
||||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||||
import { useSaleEstimateMailState } from '@/hooks/query';
|
import { SaleEstimateMailStateResponse, useSaleEstimateMailState } from '@/hooks/query';
|
||||||
|
|
||||||
interface EstimateSendMailBootValues {
|
interface EstimateSendMailBootValues {
|
||||||
estimateId: number;
|
estimateId: number;
|
||||||
|
|
||||||
estimateMailState: any;
|
estimateMailState: SaleEstimateMailStateResponse | undefined;
|
||||||
isEstimateMailState: boolean;
|
isEstimateMailState: boolean;
|
||||||
}
|
}
|
||||||
interface EstimateSendMailBootProps {
|
interface EstimateSendMailBootProps {
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
|
import { useFormikContext } from 'formik';
|
||||||
import { SendViewPreviewHeader } from '../SendMailViewDrawer/SendMailViewPreviewHeader';
|
import { SendViewPreviewHeader } from '../SendMailViewDrawer/SendMailViewPreviewHeader';
|
||||||
|
import { useEstimateSendMailBoot } from './EstimateSendMailBoot';
|
||||||
|
import { useSendEstimateMailSubject } from './hooks';
|
||||||
|
import { EstimateSendMailFormValues } from './_interfaces';
|
||||||
|
|
||||||
export function EstimateSendMailPreviewHeader() {
|
export function EstimateSendMailPreviewHeader() {
|
||||||
|
const subject = useSendEstimateMailSubject();
|
||||||
|
const { estimateMailState } = useEstimateSendMailBoot();
|
||||||
|
const {
|
||||||
|
values: { to, from },
|
||||||
|
} = useFormikContext<EstimateSendMailFormValues>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SendViewPreviewHeader
|
<SendViewPreviewHeader
|
||||||
companyName="A"
|
companyName={estimateMailState?.companyName}
|
||||||
customerName="A"
|
customerName={estimateMailState?.customerName}
|
||||||
subject={'adsfsdf'}
|
subject={subject}
|
||||||
from={['a.bouhuolia@gmail.com']}
|
from={from}
|
||||||
to={['a.bouhuolia@gmail.com']}
|
to={to}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
import { Button, Intent } from '@blueprintjs/core';
|
||||||
import { FCheckbox, FFormGroup, FInputGroup, Group, Stack } from '@/components';
|
import { FCheckbox, FFormGroup, FInputGroup, Group, Stack } from '@/components';
|
||||||
import { SendMailViewToAddressField } from '../SendMailViewDrawer/SendMailViewToAddressField';
|
import { SendMailViewToAddressField } from '../SendMailViewDrawer/SendMailViewToAddressField';
|
||||||
import { SendMailViewMessageField } from '../SendMailViewDrawer/SendMailViewMessageField';
|
import { SendMailViewMessageField } from '../SendMailViewDrawer/SendMailViewMessageField';
|
||||||
import { Button, Intent } from '@blueprintjs/core';
|
|
||||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||||
import { useDrawerActions } from '@/hooks/state';
|
import { useDrawerActions } from '@/hooks/state';
|
||||||
|
import { useSendEstimateFormatArgsOptions } from './hooks';
|
||||||
|
import { useSendMailItems } from '../SendMailViewDrawer/hooks';
|
||||||
|
|
||||||
const items: Array<any> = [];
|
|
||||||
const argsOptions: Array<any> = [];
|
|
||||||
|
|
||||||
export function EstimateSendMailFields() {
|
export function EstimateSendMailFields() {
|
||||||
|
const argOptions = useSendEstimateFormatArgsOptions();
|
||||||
|
const items = useSendMailItems();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack flex={1}>
|
||||||
<Stack spacing={0} overflow="auto" flex="1" p={'30px'}>
|
<Stack spacing={0} overflow="auto" flex="1" p={'30px'}>
|
||||||
<SendMailViewToAddressField
|
<SendMailViewToAddressField
|
||||||
toMultiSelectProps={{ items }}
|
toMultiSelectProps={{ items }}
|
||||||
@@ -22,7 +25,7 @@ export function EstimateSendMailFields() {
|
|||||||
<FInputGroup name={'subject'} large fastField />
|
<FInputGroup name={'subject'} large fastField />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<SendMailViewMessageField argsOptions={argsOptions} />
|
<SendMailViewMessageField argsOptions={argOptions} />
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<FCheckbox name={'attachPdf'} label={'Attach PDF'} />
|
<FCheckbox name={'attachPdf'} label={'Attach PDF'} />
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
export interface EstimateSendMailFormValues {}
|
import { SendMailViewFormValues } from '../SendMailViewDrawer/_types';
|
||||||
|
|
||||||
|
export interface EstimateSendMailFormValues extends SendMailViewFormValues {
|
||||||
|
attachPdf?: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { SelectOptionProps } from '@blueprintjs-formik/select';
|
||||||
|
import { useEstimateSendMailBoot } from './EstimateSendMailBoot';
|
||||||
|
import {
|
||||||
|
formatMailMessage,
|
||||||
|
transformEmailArgs,
|
||||||
|
transformFormatArgsToOptions,
|
||||||
|
} from '../SendMailViewDrawer/hooks';
|
||||||
|
import { EstimateSendMailFormValues } from './_interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the mail format arguments of estimate mail.
|
||||||
|
* @returns {Record<string, string>}
|
||||||
|
*/
|
||||||
|
export const useSendEstimateMailFormatArgs = (): Record<string, string> => {
|
||||||
|
const { estimateMailState } = useEstimateSendMailBoot();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return transformEmailArgs(estimateMailState?.formatArgs || {});
|
||||||
|
}, [estimateMailState]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the formatted estimate subject.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const useSendEstimateMailSubject = (): string => {
|
||||||
|
const { values } = useFormikContext<EstimateSendMailFormValues>();
|
||||||
|
const formatArgs = useSendEstimateMailFormatArgs();
|
||||||
|
|
||||||
|
return formatMailMessage(values?.subject, formatArgs);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the estimate format options.
|
||||||
|
* @returns {Array<SelectOptionProps>}
|
||||||
|
*/
|
||||||
|
export const useSendEstimateFormatArgsOptions =
|
||||||
|
(): Array<SelectOptionProps> => {
|
||||||
|
const formatArgs = useSendEstimateMailFormatArgs();
|
||||||
|
|
||||||
|
return transformFormatArgsToOptions(formatArgs);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the formatted estimate message.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const useSendEstimateMailMessage = (): string => {
|
||||||
|
const { values } = useFormikContext<EstimateSendMailFormValues>();
|
||||||
|
const formatArgs = useSendEstimateMailFormatArgs();
|
||||||
|
|
||||||
|
return formatMailMessage(values?.message, formatArgs);
|
||||||
|
};
|
||||||
@@ -1 +1,8 @@
|
|||||||
export interface SendMailViewFormValues {}
|
export interface SendMailViewFormValues {
|
||||||
|
from: Array<string>;
|
||||||
|
to: Array<string>;
|
||||||
|
cc: Array<string>;
|
||||||
|
bcc: Array<string>;
|
||||||
|
subject: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { chain, defaultTo, mapKeys, snakeCase, startCase } from 'lodash';
|
||||||
|
import { SendMailViewFormValues } from './_types';
|
||||||
|
|
||||||
|
export const useSendInvoiceMailForm = () => {
|
||||||
|
return useFormikContext<SendMailViewFormValues>();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the suggest items of to, cc and bcc fields.
|
||||||
|
* @returns {Array<{ value: string, text: string }>}
|
||||||
|
*/
|
||||||
|
export const useSendMailItems = (): Array<{ value: string; text: string }> => {
|
||||||
|
const { values } = useSendInvoiceMailForm();
|
||||||
|
const cc = values?.cc || [];
|
||||||
|
const bcc = values?.bcc || [];
|
||||||
|
|
||||||
|
return chain([...values?.to, ...cc, ...bcc])
|
||||||
|
.filter((email) => !!email?.trim())
|
||||||
|
.uniq()
|
||||||
|
.map((email) => ({
|
||||||
|
value: email,
|
||||||
|
text: email,
|
||||||
|
}))
|
||||||
|
.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const transformEmailArgs = (formatArgs: Record<string, string>) => {
|
||||||
|
return mapKeys(formatArgs, (_, key) =>
|
||||||
|
startCase(snakeCase(key).replace('_', ' ')),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const transformFormatArgsToOptions = (
|
||||||
|
formatArgs: Record<string, string>,
|
||||||
|
) => {
|
||||||
|
return Object.keys(formatArgs).map((key) => ({
|
||||||
|
value: key,
|
||||||
|
text: key,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const formatMailMessage = (
|
||||||
|
message: string,
|
||||||
|
args: Record<string, any>,
|
||||||
|
) => {
|
||||||
|
let formattedMessage = message;
|
||||||
|
|
||||||
|
Object.keys(args).forEach((key) => {
|
||||||
|
const variable = `{${key}}`;
|
||||||
|
const value = defaultTo(args[key], '');
|
||||||
|
|
||||||
|
formattedMessage = formattedMessage.replace(variable, value);
|
||||||
|
});
|
||||||
|
return formattedMessage;
|
||||||
|
};
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { useQueryClient, useMutation, useQuery } from 'react-query';
|
import {
|
||||||
|
useQueryClient,
|
||||||
|
useMutation,
|
||||||
|
useQuery,
|
||||||
|
UseQueryOptions,
|
||||||
|
UseQueryResult,
|
||||||
|
} from 'react-query';
|
||||||
import { useRequestQuery } from '../useQueryRequest';
|
import { useRequestQuery } from '../useQueryRequest';
|
||||||
import useApiRequest from '../useRequest';
|
import useApiRequest from '../useRequest';
|
||||||
import { transformPagination, transformToCamelCase } from '@/utils';
|
import { transformPagination, transformToCamelCase } from '@/utils';
|
||||||
@@ -257,13 +263,36 @@ export function useSendSaleEstimateMail(props = {}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SaleEstimateMailStateResponse {
|
||||||
|
attachEstimate: boolean;
|
||||||
|
companyLogoUri: string;
|
||||||
|
companyName: string;
|
||||||
|
customerName: string;
|
||||||
|
entries: Array<any>;
|
||||||
|
estimateDate: string;
|
||||||
|
formatArgs: {
|
||||||
|
customerName: string;
|
||||||
|
estimateAmount: string;
|
||||||
|
};
|
||||||
|
formattedEstimateDate: string;
|
||||||
|
from: Array<string>;
|
||||||
|
fromOptions: Array<any>;
|
||||||
|
message: string;
|
||||||
|
subject: string;
|
||||||
|
to: Array<string>;
|
||||||
|
toOptions: Array<any>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the sale estimate mail state.
|
||||||
* @param {number} estimateId
|
* @param {number} estimateId
|
||||||
* @param props
|
* @param {UseQueryOptions<SaleEstimateMailStateResponse, Error>} props
|
||||||
* @returns
|
* @returns {UseQueryResult<SaleEstimateMailStateResponse, Error>}
|
||||||
*/
|
*/
|
||||||
export function useSaleEstimateMailState(estimateId: number, props?= {}) {
|
export function useSaleEstimateMailState(
|
||||||
|
estimateId: number,
|
||||||
|
props?: UseQueryOptions<SaleEstimateMailStateResponse, Error>,
|
||||||
|
): UseQueryResult<SaleEstimateMailStateResponse, Error> {
|
||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
return useQuery([t.SALE_ESTIMATE_MAIL_OPTIONS, estimateId], () =>
|
return useQuery([t.SALE_ESTIMATE_MAIL_OPTIONS, estimateId], () =>
|
||||||
apiRequest
|
apiRequest
|
||||||
|
|||||||
Reference in New Issue
Block a user