feat(webapp): send mail notification dialogs

This commit is contained in:
Ahmed Bouhuolia
2023-12-26 15:52:38 +02:00
parent 3c8c3d8253
commit de1b7f132c
33 changed files with 737 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ import {
import { compose } from '@/utils';
import { DRAWERS } from '@/constants/drawers';
import { DialogsName } from '@/constants/dialogs';
/**
* Estimate read-only details actions bar of the drawer.
@@ -65,6 +66,10 @@ function EstimateDetailActionsBar({
const handleNotifyViaSMS = () => {
openDialog('notify-estimate-via-sms', { estimateId });
};
// Handles the estimate mail dialog.
const handleMailEstimate = () => {
openDialog(DialogsName.EstimateMail, { estimateId });
};
return (
<DrawerActionsBar>
@@ -86,6 +91,15 @@ function EstimateDetailActionsBar({
onClick={handlePrintEstimate}
/>
</Can>
<Can I={SaleEstimateAction.View} a={AbilitySubject.Estimate}>
<Button
className={Classes.MINIMAL}
text={'Mail'}
onClick={handleMailEstimate}
/>
<NavbarDivider />
</Can>
<Can I={SaleEstimateAction.Delete} a={AbilitySubject.Estimate}>
<Button
className={Classes.MINIMAL}

View File

@@ -31,6 +31,7 @@ import {
import { compose } from '@/utils';
import { BadDebtMenuItem } from './utils';
import { DRAWERS } from '@/constants/drawers';
import { DialogsName } from '@/constants/dialogs';
/**
* Invoice details action bar.
@@ -93,6 +94,10 @@ function InvoiceDetailActionsBar({
openAlert('cancel-bad-debt', { invoiceId });
};
const handleMailInvoice = () => {
openDialog(DialogsName.InvoiceMail, { invoiceId });
};
return (
<DrawerActionsBar>
<NavbarGroup>
@@ -116,6 +121,13 @@ function InvoiceDetailActionsBar({
</If>
<NavbarDivider />
</Can>
<Can I={SaleInvoiceAction.View} a={AbilitySubject.Invoice}>
<Button
text={'Mail'}
onClick={handleMailInvoice}
className={Classes.MINIMAL}
/>
</Can>
<Can I={SaleInvoiceAction.View} a={AbilitySubject.Invoice}>
<Button
className={Classes.MINIMAL}

View File

@@ -28,6 +28,7 @@ import {
import { compose } from '@/utils';
import { DRAWERS } from '@/constants/drawers';
import { DialogsName } from '@/constants/dialogs';
/**
* Payment receive actions bar.
@@ -68,6 +69,10 @@ function PaymentReceiveActionsBar({
openDialog('payment-pdf-preview', { paymentReceiveId });
};
const handleMailPaymentReceive = () => {
openDialog(DialogsName.PaymentMail, { paymentReceiveId });
};
return (
<DrawerActionsBar>
<NavbarGroup>
@@ -88,6 +93,13 @@ function PaymentReceiveActionsBar({
onClick={handlePrintPaymentReceive}
/>
</Can>
<Can I={PaymentReceiveAction.View} a={AbilitySubject.PaymentReceive}>
<Button
className={Classes.MINIMAL}
text={'Mail'}
onClick={handleMailPaymentReceive}
/>
</Can>
<Can I={PaymentReceiveAction.Delete} a={AbilitySubject.PaymentReceive}>
<Button
className={Classes.MINIMAL}

View File

@@ -24,6 +24,7 @@ import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
import { SaleReceiptAction, AbilitySubject } from '@/constants/abilityOption';
import { safeCallback, compose } from '@/utils';
import { DRAWERS } from '@/constants/drawers';
import { DialogsName } from '@/constants/dialogs';
/**
* Receipt details actions bar.
@@ -60,6 +61,9 @@ function ReceiptDetailActionBar({
const handleNotifyViaSMS = () => {
openDialog('notify-receipt-via-sms', { receiptId });
};
const handleReceiptMail = () => {
openDialog(DialogsName.ReceiptMail, { receiptId });
}
return (
<DrawerActionsBar>
@@ -81,6 +85,13 @@ function ReceiptDetailActionBar({
onClick={safeCallback(onPrintReceipt)}
/>
</Can>
<Can I={SaleReceiptAction.View} a={AbilitySubject.Receipt}>
<Button
className={Classes.MINIMAL}
text={'Mail'}
onClick={handleReceiptMail}
/>
</Can>
<Can I={SaleReceiptAction.Delete} a={AbilitySubject.Receipt}>
<Button
className={Classes.MINIMAL}

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const EstimateMailDialogContent = React.lazy(
() => import('./EstimateMailDialogContent'),
);
/**
* Invoice mail dialog.
*/
function EstimateMailDialog({
dialogName,
payload: { estimateId = null },
isOpen,
}) {
return (
<Dialog
name={dialogName}
title={'Estiomate Mail'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
>
<DialogSuspense>
<EstimateMailDialogContent
dialogName={dialogName}
estimateId={estimateId}
/>
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(EstimateMailDialog);

View File

@@ -0,0 +1,43 @@
// @ts-nocheck
import React, { createContext } from 'react';
import { useSaleEstimateDefaultOptions } from '@/hooks/query';
import { DialogContent } from '@/components';
interface EstimateMailDialogBootValues {
estimateId: number;
mailOptions: any;
}
const EstimateMailDialagBoot = createContext<EstimateMailDialogBootValues>();
interface EstimateMailDialogBootProps {
estimateId: number;
children: React.ReactNode;
}
/**
* Estimate mail dialog boot provider.
*/
function EstimateMailDialogBoot({
estimateId,
...props
}: EstimateMailDialogBootProps) {
const { data: mailOptions, isLoading: isMailOptionsLoading } =
useSaleEstimateDefaultOptions(estimateId);
const provider = {
mailOptions,
isMailOptionsLoading,
};
return (
<DialogContent isLoading={isMailOptionsLoading}>
<EstimateMailDialagBoot.Provider value={provider} {...props} />
</DialogContent>
);
}
const useEstimateMailDialogBoot = () =>
React.useContext<EstimateMailDialogBootValues>(EstimateMailDialagBoot);
export { EstimateMailDialogBoot, useEstimateMailDialogBoot };

View File

@@ -0,0 +1,18 @@
import React from 'react';
import { EstimateMailDialogBoot } from './EstimateMailDialogBoot';
import { EstimateMailDialogForm } from './EstimateMailDialogForm';
interface EstimateMailDialogContentProps {
dialogName: string;
estimateId: number;
}
export default function EstimateMailDialogContent({
dialogName,
estimateId,
}: EstimateMailDialogContentProps) {
return (
<EstimateMailDialogBoot estimateId={estimateId}>
<EstimateMailDialogForm />
</EstimateMailDialogBoot>
)
}

View File

@@ -0,0 +1,31 @@
import { Formik } from 'formik';
import { useEstimateMailDialogBoot } from './EstimateMailDialogBoot';
import { transformToForm } from '@/utils';
import { SendMailNotificationForm } from '@/containers/SendMailNotification';
import { castArray } from 'lodash';
const initialFormValues = {
from: [],
to: [],
subject: '',
message: '',
};
export function EstimateMailDialogForm() {
const { mailOptions } = useEstimateMailDialogBoot();
const initialValues = {
...initialFormValues,
...transformToForm(mailOptions, initialFormValues),
from: mailOptions.from ? castArray(mailOptions.from) : [],
to: mailOptions.to ? castArray(mailOptions.to) : [],
};
const handleSubmit = () => {};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
<SendMailNotificationForm />
</Formik>
);
}

View File

@@ -0,0 +1 @@
export * from './EstimateMailDialog';

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const InvoiceMailDialogContent = React.lazy(
() => import('./InvoiceMailDialogContent'),
);
/**
* Invoice mail dialog.
*/
function InvoiceMailDialog({
dialogName,
payload: { invoiceId = null },
isOpen,
}) {
return (
<Dialog
name={dialogName}
title={'Invoice Mail'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
>
<DialogSuspense>
<InvoiceMailDialogContent
dialogName={dialogName}
invoiceId={invoiceId}
/>
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(InvoiceMailDialog);

View File

@@ -0,0 +1,43 @@
// @ts-nocheck
import React, { createContext } from 'react';
import { useSaleInvoiceDefaultOptions } from '@/hooks/query';
import { DialogContent } from '@/components';
interface InvoiceMailDialogBootValues {
invoiceId: number;
mailOptions: any;
}
const InvoiceMailDialagBoot = createContext<InvoiceMailDialogBootValues>();
interface InvoiceMailDialogBootProps {
invoiceId: number;
children: React.ReactNode;
}
/**
* Invoice mail dialog boot provider.
*/
function InvoiceMailDialogBoot({
invoiceId,
...props
}: InvoiceMailDialogBootProps) {
const { data: mailOptions, isLoading: isMailOptionsLoading } =
useSaleInvoiceDefaultOptions(invoiceId);
const provider = {
mailOptions,
isMailOptionsLoading,
};
return (
<DialogContent isLoading={isMailOptionsLoading}>
<InvoiceMailDialagBoot.Provider value={provider} {...props} />
</DialogContent>
);
}
const useInvoiceMailDialogBoot = () =>
React.useContext<InvoiceMailDialogBootValues>(InvoiceMailDialagBoot);
export { InvoiceMailDialogBoot, useInvoiceMailDialogBoot };

View File

@@ -0,0 +1,17 @@
import { InvoiceMailDialogBoot } from './InvoiceMailDialogBoot';
import { InvoiceMailDialogForm } from './InvoiceMailDialogForm';
interface InvoiceMailDialogContentProps {
dialogName: string;
invoiceId: number;
}
export default function InvoiceMailDialogContent({
dialogName,
invoiceId,
}: InvoiceMailDialogContentProps) {
return (
<InvoiceMailDialogBoot invoiceId={invoiceId}>
<InvoiceMailDialogForm />
</InvoiceMailDialogBoot>
);
}

View File

@@ -0,0 +1,29 @@
import { Formik } from 'formik';
import { castArray } from 'lodash';
import { SendMailNotificationForm } from '@/containers/SendMailNotification';
import { useInvoiceMailDialogBoot } from './InvoiceMailDialogBoot';
import { transformToForm } from '@/utils';
const initialFormValues = {
from: [],
to: [],
subject: '',
message: '',
};
export function InvoiceMailDialogForm() {
const { mailOptions } = useInvoiceMailDialogBoot();
const initialValues = {
...initialFormValues,
...transformToForm(mailOptions, initialFormValues),
from: mailOptions.from ? castArray(mailOptions.from) : [],
to: mailOptions.to ? castArray(mailOptions.to) : [],
};
const handleSubmit = () => {};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
<SendMailNotificationForm />
</Formik>
);
}

View File

@@ -0,0 +1 @@
export * from './InvoiceMailDialog';

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const PaymentMailDialogContent = React.lazy(
() => import('./PaymentMailDialogContent'),
);
/**
* Payment mail dialog.
*/
function PaymentMailDialog({
dialogName,
payload: { paymentReceiveId = null },
isOpen,
}) {
return (
<Dialog
name={dialogName}
title={'Payment Mail'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
>
<DialogSuspense>
<PaymentMailDialogContent
dialogName={dialogName}
paymentReceiveId={paymentReceiveId}
/>
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(PaymentMailDialog);

View File

@@ -0,0 +1,44 @@
// @ts-nocheck
import React, { createContext } from 'react';
import { usePaymentReceiveDefaultOptions } from '@/hooks/query';
import { DialogContent } from '@/components';
interface PaymentMailDialogBootValues {
paymentReceiveId: number;
mailOptions: any;
}
const PaymentMailDialogBootContext =
createContext<PaymentMailDialogBootValues>();
interface PaymentMailDialogBootProps {
paymentReceiveId: number;
children: React.ReactNode;
}
/**
* Payment mail dialog boot provider.
*/
function PaymentMailDialogBoot({
paymentReceiveId,
...props
}: PaymentMailDialogBootProps) {
const { data: mailOptions, isLoading: isMailOptionsLoading } =
usePaymentReceiveDefaultOptions(paymentReceiveId);
const provider = {
mailOptions,
isMailOptionsLoading,
};
return (
<DialogContent isLoading={isMailOptionsLoading}>
<PaymentMailDialogBootContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const usePaymentMailDialogBoot = () =>
React.useContext<PaymentMailDialogBootValues>(PaymentMailDialogBootContext);
export { PaymentMailDialogBoot, usePaymentMailDialogBoot };

View File

@@ -0,0 +1,17 @@
import { PaymentMailDialogBoot } from './PaymentMailDialogBoot';
import { PaymentMailDialogForm } from './PaymentMailDialogForm';
interface PaymentMailDialogContentProps {
dialogName: string;
paymentReceiveId: number;
}
export default function PaymentMailDialogContent({
dialogName,
paymentReceiveId,
}: PaymentMailDialogContentProps) {
return (
<PaymentMailDialogBoot paymentReceiveId={paymentReceiveId}>
<PaymentMailDialogForm />
</PaymentMailDialogBoot>
);
}

View File

@@ -0,0 +1,29 @@
import { Formik } from 'formik';
import { castArray } from 'lodash';
import { SendMailNotificationForm } from '@/containers/SendMailNotification';
import { usePaymentMailDialogBoot } from './PaymentMailDialogBoot';
import { transformToForm } from '@/utils';
const initialFormValues = {
from: [],
to: [],
subject: '',
message: '',
};
export function PaymentMailDialogForm() {
const { mailOptions } = usePaymentMailDialogBoot();
const initialValues = {
...initialFormValues,
...transformToForm(mailOptions, initialFormValues),
from: mailOptions.from ? castArray(mailOptions.from) : [],
to: mailOptions.to ? castArray(mailOptions.to) : [],
};
const handleSubmit = () => {};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
<SendMailNotificationForm />
</Formik>
);
}

View File

@@ -0,0 +1 @@
export * from './PaymentMailDialog';

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import React from 'react';
import { Dialog, DialogSuspense } from '@/components';
import withDialogRedux from '@/components/DialogReduxConnect';
import { compose } from '@/utils';
const ReceiptMailDialogContent = React.lazy(
() => import('./ReceiptMailDialogContent'),
);
/**
* Invoice mail dialog.
*/
function ReceiptMailDialog({
dialogName,
payload: { receiptId = null },
isOpen,
}) {
return (
<Dialog
name={dialogName}
title={'Receipt Mail'}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
>
<DialogSuspense>
<ReceiptMailDialogContent
dialogName={dialogName}
receiptId={receiptId}
/>
</DialogSuspense>
</Dialog>
);
}
export default compose(withDialogRedux())(ReceiptMailDialog);

View File

@@ -0,0 +1,44 @@
// @ts-nocheck
import React, { createContext } from 'react';
import { useSaleReceiptDefaultOptions } from '@/hooks/query';
import { DialogContent } from '@/components';
interface ReceiptMailDialogBootValues {
receiptId: number;
mailOptions: any;
}
const ReceiptMailDialogBootContext =
createContext<ReceiptMailDialogBootValues>();
interface ReceiptMailDialogBootProps {
receiptId: number;
children: React.ReactNode;
}
/**
* Receipt mail dialog boot provider.
*/
function ReceiptMailDialogBoot({
receiptId,
...props
}: ReceiptMailDialogBootProps) {
const { data: mailOptions, isLoading: isMailOptionsLoading } =
useSaleReceiptDefaultOptions(receiptId);
const provider = {
mailOptions,
isMailOptionsLoading,
};
return (
<DialogContent isLoading={isMailOptionsLoading}>
<ReceiptMailDialogBootContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useReceiptMailDialogBoot = () =>
React.useContext<ReceiptMailDialogBootValues>(ReceiptMailDialogBootContext);
export { ReceiptMailDialogBoot, useReceiptMailDialogBoot };

View File

@@ -0,0 +1,18 @@
import React from 'react';
import { ReceiptMailDialogBoot } from './ReceiptMailDialogBoot';
import { ReceiptMailDialogForm } from './ReceiptMailDialogForm';
interface ReceiptMailDialogContentProps {
dialogName: string
receiptId: number;
}
export default function ReceiptMailDialogContent({
dialogName,
receiptId,
}: ReceiptMailDialogContentProps) {
return (
<ReceiptMailDialogBoot receiptId={receiptId}>
<ReceiptMailDialogForm />
</ReceiptMailDialogBoot>
);
}

View File

@@ -0,0 +1,29 @@
import { Formik } from 'formik';
import { castArray } from 'lodash';
import { SendMailNotificationForm } from '@/containers/SendMailNotification';
import { useReceiptMailDialogBoot } from './ReceiptMailDialogBoot';
import { transformToForm } from '@/utils';
const initialFormValues = {
from: [],
to: [],
subject: '',
message: '',
};
export function ReceiptMailDialogForm() {
const { mailOptions } = useReceiptMailDialogBoot();
const initialValues = {
...initialFormValues,
...transformToForm(mailOptions, initialFormValues),
from: mailOptions.from ? castArray(mailOptions.from) : [],
to: mailOptions.to ? castArray(mailOptions.to) : [],
};
const handleSubmit = () => {};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
<SendMailNotificationForm />
</Formik>
);
}

View File

@@ -0,0 +1 @@
export * from './ReceiptMailDialog';

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
import { Form } from 'formik';
import { FFormGroup, FInputGroup, FMultiSelect } from '@/components';
export function SendMailNotificationForm() {
return (
<Form>
<FFormGroup label={'From'} name={'from'} inline={true} fastField={true}>
<FMultiSelect
items={[]}
name={'from'}
placeholder=""
popoverProps={{ minimal: true }}
/>
</FFormGroup>
<FFormGroup label={'To'} name={'to'} inline={true} fastField={true}>
<FMultiSelect
items={[]}
name={'to'}
placeholder=""
popoverProps={{ minimal: true }}
/>
</FFormGroup>
<FFormGroup
label={'Subject'}
name={'subject'}
inline={true}
fastField={true}
>
<FInputGroup name={'subject'} />
</FFormGroup>
</Form>
);
}

View File

@@ -0,0 +1 @@
export * from './SendMailNotificationForm';