mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
feat: Invoice mail receipt preview
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { Spinner, Tab } from '@blueprintjs/core';
|
||||
import {
|
||||
InvoicePaperTemplate,
|
||||
InvoicePaperTemplateProps,
|
||||
@@ -19,6 +20,19 @@ import { BrandingTemplateForm } from '@/containers/BrandingTemplates/BrandingTem
|
||||
import { useElementCustomizeContext } from '@/containers/ElementCustomize/ElementCustomizeProvider';
|
||||
import { initialValues } from './constants';
|
||||
import { useIsTemplateNamedFilled } from '@/containers/BrandingTemplates/utils';
|
||||
import { InvoiceCustomizeTabs } from './InvoiceCustomizeTabs';
|
||||
|
||||
const InvoicePaymentPagePreview = lazy(() =>
|
||||
import('@/containers/PaymentPortal/InvoicePaymentPagePreview').then(
|
||||
(module) => ({ default: module.InvoicePaymentPagePreview }),
|
||||
),
|
||||
);
|
||||
|
||||
const InvoiceMailReceiptPreview = lazy(() =>
|
||||
import(
|
||||
'@/containers/Sales/Invoices/InvoiceCustomize/InvoiceMailReceiptPreview'
|
||||
).then((module) => ({ default: module.InvoiceMailReceiptPreview })),
|
||||
);
|
||||
|
||||
/**
|
||||
* Invoice branding template customize.
|
||||
@@ -56,7 +70,39 @@ function InvoiceCustomizeFormContent() {
|
||||
return (
|
||||
<ElementCustomizeContent>
|
||||
<ElementCustomize.PaperTemplate>
|
||||
<InvoicePaperTemplateFormConnected />
|
||||
<InvoiceCustomizeTabs
|
||||
defaultSelectedTabId={'pdf-document'}
|
||||
id={'customize-preview-tabs'}
|
||||
renderActiveTabPanelOnly
|
||||
>
|
||||
<Tab
|
||||
id="pdf-document"
|
||||
title={'PDF document'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoicePaperTemplateFormConnected />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Tab
|
||||
id={'payment-page'}
|
||||
title={'Payment page'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoicePaymentPagePreview />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Tab
|
||||
id={'email-receipt'}
|
||||
title={'Email receipt'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoiceMailReceiptPreview mx={'auto'} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
</InvoiceCustomizeTabs>
|
||||
</ElementCustomize.PaperTemplate>
|
||||
|
||||
<ElementCustomize.FieldsTab id={'general'} label={'General'}>
|
||||
@@ -90,7 +136,6 @@ const withInvoicePreviewTemplateProps = <P extends object>(
|
||||
...brandingState,
|
||||
...values,
|
||||
};
|
||||
|
||||
return <Component {...(props as P)} {...mergedProps} />;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Tabs, TabsProps } from '@blueprintjs/core';
|
||||
|
||||
interface InvoiceCustomizeTabsProps extends TabsProps { }
|
||||
|
||||
export function InvoiceCustomizeTabs(props: InvoiceCustomizeTabsProps) {
|
||||
return (
|
||||
<Tabs
|
||||
className={css`
|
||||
.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;
|
||||
}
|
||||
`}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { css } from '@emotion/css';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { Group, Stack, StackProps } from '@/components';
|
||||
|
||||
export interface InvoiceMailReceiptProps extends StackProps {
|
||||
companyLogoUri?: string;
|
||||
message: string;
|
||||
companyName: string;
|
||||
invoiceNumber: string;
|
||||
dueDate: string;
|
||||
items?: Array<{ label: string; total: string; quantity: string | number }>;
|
||||
total: string;
|
||||
dueAmount: string;
|
||||
totalLabel?: string;
|
||||
dueAmountLabel?: string;
|
||||
viewInvoiceButtonLabel?: string;
|
||||
viewInvoiceButtonOnClick?: () => void;
|
||||
invoiceNumberLabel?: string;
|
||||
}
|
||||
|
||||
export function InvoiceMailReceipt({
|
||||
companyLogoUri,
|
||||
message,
|
||||
companyName,
|
||||
total,
|
||||
invoiceNumber,
|
||||
dueDate,
|
||||
dueAmount,
|
||||
items,
|
||||
viewInvoiceButtonLabel = 'View Invoice',
|
||||
viewInvoiceButtonOnClick,
|
||||
totalLabel = 'Total',
|
||||
dueAmountLabel = 'Due Amount',
|
||||
invoiceNumberLabel = 'Invoice #',
|
||||
...restProps
|
||||
}: InvoiceMailReceiptProps) {
|
||||
return (
|
||||
<Stack
|
||||
bg="white"
|
||||
w={'100%'}
|
||||
maxWidth={'500px'}
|
||||
p={'35px 25px'}
|
||||
borderRadius={'5px'}
|
||||
boxShadow={'0 10px 15px rgba(0, 0, 0, 0.05)'}
|
||||
color={'black'}
|
||||
{...restProps}
|
||||
>
|
||||
<Stack spacing={16} textAlign={'center'}>
|
||||
{companyLogoUri && (
|
||||
<x.div h={'90px'} w={'90px'} bg="#F2F2F2" mx="auto"></x.div>
|
||||
)}
|
||||
<Stack spacing={8}>
|
||||
<x.h1 m={0} fontSize={'18px'} fontWeight={500} color="#404854">
|
||||
{companyName}
|
||||
</x.h1>
|
||||
|
||||
<x.h3 color="#383E47" fontWeight={500}>
|
||||
{total}
|
||||
</x.h3>
|
||||
|
||||
<x.span fontSize={'13px'} color="#404854">
|
||||
{invoiceNumberLabel} {invoiceNumber}
|
||||
</x.span>
|
||||
|
||||
<x.span fontSize={'13px'} color="#404854">
|
||||
Due {dueDate}
|
||||
</x.span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<x.p m={0} whiteSpace={'pre-line'} color="#252A31">
|
||||
{message}
|
||||
</x.p>
|
||||
|
||||
<Button
|
||||
large
|
||||
intent={Intent.PRIMARY}
|
||||
className={css`
|
||||
&.bp4-large {
|
||||
min-height: 38px;
|
||||
}
|
||||
`}
|
||||
onClick={viewInvoiceButtonOnClick}
|
||||
>
|
||||
{viewInvoiceButtonLabel}
|
||||
</Button>
|
||||
|
||||
<Stack spacing={0}>
|
||||
{items?.map((item, key) => (
|
||||
<Group
|
||||
key={key}
|
||||
h={'40px'}
|
||||
position={'apart'}
|
||||
borderBottomStyle="solid"
|
||||
borderBottomWidth={'1px'}
|
||||
borderBottomColor={'#D9D9D9'}
|
||||
borderTopStyle="solid"
|
||||
borderTopColor={'#D9D9D9'}
|
||||
borderTopWidth={'1px'}
|
||||
>
|
||||
<x.span>{item.label}</x.span>
|
||||
<x.span>
|
||||
{item.quantity} x {item.total}
|
||||
</x.span>
|
||||
</Group>
|
||||
))}
|
||||
|
||||
<Group
|
||||
h={'40px'}
|
||||
position={'apart'}
|
||||
borderBottomStyle="solid"
|
||||
borderBottomWidth={'1px'}
|
||||
borderColor={'#000'}
|
||||
>
|
||||
<x.span fontWeight={500}>{totalLabel}</x.span>
|
||||
<x.span fontWeight={600} fontSize={15}>
|
||||
{total}
|
||||
</x.span>
|
||||
</Group>
|
||||
|
||||
<Group
|
||||
h={'40px'}
|
||||
position={'apart'}
|
||||
borderBottomStyle="solid"
|
||||
borderBottomWidth={'1px'}
|
||||
borderBottomColor={'#000'}
|
||||
>
|
||||
<x.span fontWeight={500}>{dueAmountLabel}</x.span>
|
||||
<x.span fontWeight={600} fontSize={15}>
|
||||
{dueAmount}
|
||||
</x.span>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
InvoiceMailReceipt,
|
||||
InvoiceMailReceiptProps,
|
||||
} from './InvoiceMailReceipt';
|
||||
|
||||
export interface InvoiceMailReceiptPreviewProps
|
||||
extends Partial<InvoiceMailReceiptProps> { }
|
||||
|
||||
const receiptMessage = `Hi Ahmed,
|
||||
|
||||
Here’s invoice INV-0002 for AED 0.00
|
||||
|
||||
The amount outstanding of AED $100,00 is due on 2 October 2024
|
||||
|
||||
View your bill online From your online you can print a PDF or pay your outstanding bills,
|
||||
|
||||
If you have any questions, please let us know,
|
||||
|
||||
Thanks,
|
||||
Mohamed
|
||||
`;
|
||||
|
||||
export function InvoiceMailReceiptPreview(
|
||||
props: InvoiceMailReceiptPreviewProps,
|
||||
) {
|
||||
const propsWithDefaults = {
|
||||
message: receiptMessage,
|
||||
companyName: 'Bigcapital Technology, Inc.',
|
||||
total: '$1,000.00',
|
||||
invoiceNumber: 'INV-0001',
|
||||
dueDate: '2 Oct 2024',
|
||||
dueAmount: '$1,000.00',
|
||||
items: [{ label: 'Line Item #1', total: '$1000.00', quantity: 1 }],
|
||||
companyLogoUri: ' ',
|
||||
...props,
|
||||
};
|
||||
return <InvoiceMailReceipt {...propsWithDefaults} />;
|
||||
}
|
||||
Reference in New Issue
Block a user