feat: send invoice mail receipt drawer

This commit is contained in:
Ahmed Bouhuolia
2024-10-23 16:30:39 +02:00
parent 03e6372f14
commit c321d90575
12 changed files with 330 additions and 5 deletions

View File

@@ -23,8 +23,6 @@ function BrandingTemplatesDrawerRoot({
isOpen={isOpen}
name={name}
payload={payload}
size={'600px'}
style={{ borderLeftColor: '#cbcbcb' }}
>
<DrawerSuspense>
<BrandingTemplatesContent />

View File

@@ -4,7 +4,7 @@ import {
} from './InvoiceMailReceipt';
export interface InvoiceMailReceiptPreviewProps
extends Partial<InvoiceMailReceiptProps> { }
extends Partial<InvoiceMailReceiptProps> {}
const receiptMessage = `Hi Ahmed,
@@ -30,7 +30,7 @@ export function InvoiceMailReceiptPreview(
invoiceNumber: 'INV-0001',
dueDate: '2 Oct 2024',
dueAmount: '$1,000.00',
items: [{ label: 'Line Item #1', total: '$1000.00', quantity: 1 }],
items: [{ label: 'Web development', total: '$1000.00', quantity: 1 }],
companyLogoUri: ' ',
...props,
};

View File

@@ -0,0 +1,26 @@
import { Group, Stack } from '@/components';
import { Classes } from '@blueprintjs/core';
import { InvoiceSendMailBoot } from './InvoiceSendMailContentBoot';
import { InvoiceSendMailForm } from './InvoiceSendMailForm';
import { InvoiceSendMailHeader } from './InvoiceSendMailHeader';
import { InvoiceSendMailPreview } from './InvoiceSendMailPreview';
import { InvoiceSendMailFields } from './InvoiceSendMailFields';
export function InvoiceSendMailContent() {
return (
<Stack className={Classes.DRAWER_BODY}>
<InvoiceSendMailBoot>
<InvoiceSendMailForm>
<Stack spacing={0} flex={1} overflow="hidden">
<InvoiceSendMailHeader label={'Send Invoice Mail'} />
<Group flex={1} overflow="auto" spacing={0} alignItems={'stretch'}>
<InvoiceSendMailFields />
<InvoiceSendMailPreview />
</Group>
</Stack>
</InvoiceSendMailForm>
</InvoiceSendMailBoot>
</Stack>
);
}

View File

@@ -0,0 +1,32 @@
import React, { createContext, useContext } from 'react';
import { Spinner } from '@blueprintjs/core';
interface InvoiceSendMailBootValues {}
interface InvoiceSendMailBootProps {
children: React.ReactNode;
}
const InvoiceSendMailContentBootContext =
createContext<InvoiceSendMailBootValues>({} as InvoiceSendMailBootValues);
export const InvoiceSendMailBoot = ({ children }: InvoiceSendMailBootProps) => {
const isLoading = false;
if (isLoading) {
return <Spinner size={20} />;
}
const value = {};
return (
<InvoiceSendMailContentBootContext.Provider value={value}>
{children}
</InvoiceSendMailContentBootContext.Provider>
);
};
InvoiceSendMailBoot.displayName = 'InvoiceSendMailBoot';
export const useInvoiceSendMailBoot = () => {
return useContext<InvoiceSendMailBootValues>(
InvoiceSendMailContentBootContext,
);
};

View File

@@ -0,0 +1,30 @@
import * as R from 'ramda';
import { Drawer, DrawerSuspense } from '@/components';
import { InvoiceSendMailContent } from './InvoiceSendMailContent';
import withDrawers from '@/containers/Drawer/withDrawers';
interface InvoiceSendMailDrawerProps {
name: string;
isOpen?: boolean;
payload?: any;
}
function InvoiceSendMailDrawerRoot({
name,
// #withDrawer
isOpen,
payload,
}: InvoiceSendMailDrawerProps) {
return (
<Drawer isOpen={isOpen} name={name} size={'100%'} payload={payload}>
<DrawerSuspense>
<InvoiceSendMailContent />
</DrawerSuspense>
</Drawer>
);
}
export const InvoiceSendMailDrawer = R.compose(withDrawers())(
InvoiceSendMailDrawerRoot,
);

View File

@@ -0,0 +1,61 @@
import { Button, Intent } from "@blueprintjs/core";
import { useFormikContext } from "formik";
import { FFormGroup, FInputGroup, Group, Stack } from "@/components";
import { useDrawerContext } from "@/components/Drawer/DrawerProvider";
import { useDrawerActions } from "@/hooks/state";
export function InvoiceSendMailFields() {
return (
<Stack bg="white" flex={'1'} spacing={0} borderRight="1px solid #dcdcdd">
<Stack overflow="auto" flex="1" p={'30px'}>
<FFormGroup label={'Submit'} name={'subject'}>
<FInputGroup name={'subject'} large />
</FFormGroup>
<FFormGroup label={'Message'} name={'message'}>
<FInputGroup name={'message'} large />
</FFormGroup>
</Stack>
<InvoiceSendMailFooter />
</Stack>
);
}
function InvoiceSendMailFooter() {
const { isSubmitting } = useFormikContext();
const { name } = useDrawerContext();
const { closeDrawer } = useDrawerActions();
const handleClose = () => {
closeDrawer(name);
};
return (
<Group
py={'12px'}
px={'16px'}
borderTop="1px solid #d8d8d9"
position={'apart'}
>
<Group spacing={10} ml={'auto'}>
<Button
disabled={isSubmitting}
onClick={handleClose}
style={{ minWidth: '65px' }}
>
Close
</Button>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
style={{ minWidth: '85px' }}
type="submit"
>
Send Mail
</Button>
</Group>
</Group>
);
}

View File

@@ -0,0 +1,54 @@
import * as Yup from 'yup';
import { Form, Formik, FormikHelpers } from 'formik';
import { css } from '@emotion/css';
const initialValues = {
subject: '',
message: '',
to: '',
cc: '',
};
interface InvoiceSendMailFormValues {
subject: string;
message: string;
to: string;
cc: string;
}
const InvoiceSendMailFormSchema = Yup.object().shape({
subject: Yup.string().required('Subject is required'),
message: Yup.string().required('Message is required'),
to: Yup.string().email('Invalid email').required('To address is required'),
cc: Yup.string().email('Invalid email'),
});
interface InvoiceSendMailFormProps {
children: React.ReactNode;
}
export function InvoiceSendMailForm({ children }: InvoiceSendMailFormProps) {
//
const handleSubmit = (
values: InvoiceSendMailFormValues,
{ setSubmitting }: FormikHelpers<InvoiceSendMailFormValues>,
) => {};
return (
<Formik
initialValues={initialValues}
validationSchema={InvoiceSendMailFormSchema}
onSubmit={handleSubmit}
>
<Form
className={css`
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
`}
>
{children}
</Form>
</Formik>
);
}

View File

@@ -0,0 +1,52 @@
import { Button, Classes } from "@blueprintjs/core";
import { Group, Icon } from "@/components";
import { useDrawerContext } from "@/components/Drawer/DrawerProvider";
import { useDrawerActions } from "@/hooks/state";
interface ElementCustomizeHeaderProps {
label?: string;
children?: React.ReactNode;
closeButton?: boolean;
onClose?: () => void;
}
export function InvoiceSendMailHeader({
label,
closeButton = true,
onClose,
children,
}: ElementCustomizeHeaderProps) {
const { name } = useDrawerContext();
const { closeDrawer } = useDrawerActions();
const handleClose = () => {
closeDrawer(name);
};
return (
<Group
p={'10px'}
pl={'15px'}
bg="white"
alignItems={'center'}
boxShadow={'0 1px 0 rgba(17, 20, 24, .15)'}
zIndex={1}
style={{ position: 'relative' }}
>
{label && (
<h1 style={{ margin: 0, fontSize: 20, fontWeight: 500, color: '#666' }}>
{label}
</h1>
)}
{closeButton && (
<Button
aria-label="Close"
className={Classes.DIALOG_CLOSE_BUTTON}
icon={<Icon icon={'smallCross'} color={'#000'} />}
minimal={true}
onClick={handleClose}
style={{ marginLeft: 'auto' }}
/>
)}
</Group>
);
}

View File

@@ -0,0 +1,68 @@
import { Tab, Tabs } from "@blueprintjs/core";
import { css } from "@emotion/css";
import { Box, Stack } from "@/components";
import { InvoiceMailReceiptPreview } from "../InvoiceCustomize/InvoiceMailReceiptPreview";
import { InvoicePaperTemplate } from "../InvoiceCustomize/InvoicePaperTemplate";
export function InvoiceSendMailPreview() {
return (
<Stack bg="#F5F5F5" flex={'1'} minWidth="850px">
<Tabs
id={'preview'}
defaultSelectedTabId={'payment-page'}
className={css`
overflow: hidden;
flex: 1 1;
display: flex;
flex-direction: column;
.bp4-tab-list {
padding: 0 20px;
background: #fff;
border-bottom: 1px solid #dcdcdd;
}
.bp4-tab {
line-height: 40px;
}
.bp4-tab:not([aria-selected='true']) {
color: #5f6b7c;
}
.bp4-tab-indicator-wrapper .bp4-tab-indicator {
height: 2px;
}
.bp4-tab-panel {
margin: 0;
overflow: auto;
}
`}
>
<Tab
id={'payment-page'}
title={'Payment page'}
panel={
<Box px={4} pt={8} pb={16}>
<InvoiceMailReceiptPreview
className={css`
margin: 0 auto;
`}
/>
</Box>
}
/>
<Tab
id="pdf-document"
title={'PDF document'}
panel={
<Box px={4} py={6}>
<InvoicePaperTemplate
className={css`
margin: 0 auto;
`}
/>
</Box>
}
/>
</Tabs>
</Stack>
);
}

View File

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