feat: Paper template reusable

This commit is contained in:
Ahmed Bouhuolia
2024-09-10 18:37:38 +02:00
parent 317adfa0de
commit 77a1e35ff4
9 changed files with 777 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import { Classes } from '@blueprintjs/core';
import { ElementCustomize } from '../../../ElementCustomize/ElementCustomize';
import { CreditNoteCustomizeGeneralField } from './CreditNoteCustomizeGeneralFields';
import { CreditNoteCustomizeContentFields } from './CreditNoteCutomizeContentFields';
import { CreditNotePaperTemplate } from './CreditNotePaperTemplate';
import { CreditNoteCustomizeValues } from './types';
import { initialValues } from './constants';
@@ -18,7 +19,7 @@ export default function CreditNoteCustomizeContent() {
onSubmit={handleFormSubmit}
>
<ElementCustomize.PaperTemplate>
{/* <InvoicePaperTemplate /> */}
<CreditNotePaperTemplate />
</ElementCustomize.PaperTemplate>
<ElementCustomize.FieldsTab id={'general'} label={'General'}>

View File

@@ -0,0 +1,161 @@
import { Group, Stack } from '@/components';
import { PaperTemplate, PaperTemplateProps } from '../../Invoices/InvoiceCustomize/PaperTemplate';
export interface CreditNotePaperTemplateProps extends PaperTemplateProps {
billedToAddress?: Array<string>;
billedFromAddress?: Array<string>;
total?: string;
showTotal?: boolean;
totalLabel?: string;
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
showCustomerNote?: boolean;
customerNote?: string;
customerNoteLabel?: string;
showTermsConditions?: boolean;
termsConditions?: string;
termsConditionsLabel?: string;
lines?: Array<{
item: string;
description: string;
rate: string;
quantity: string;
total: string;
}>;
creditNoteDateLabel?: string;
showCreditNoteDate?: boolean;
creditNoteDate?: string;
creditNoteNumebr?: string;
creditNoteNumberLabel?: string;
showCreditNoteNumber?: boolean;
}
export function CreditNotePaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo = true,
companyLogo,
billedToAddress = [
'Bigcapital Technology, Inc.',
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
billedFromAddress = [
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
showCustomerNote = true,
customerNote = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
customerNoteLabel = 'Customer Note',
showTermsConditions = true,
termsConditions = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
termsConditionsLabel = 'Terms & Conditions',
lines = [
{
item: 'Simply dummy text',
description: 'Simply dummy text of the printing and typesetting',
rate: '1',
quantity: '1000',
total: '$1000.00',
},
],
showCreditNoteNumber = true,
creditNoteNumberLabel = 'Credit Note Number',
creditNoteNumebr = '346D3D40-0001',
creditNoteDate = 'September 3, 2024',
showCreditNoteDate = true,
creditNoteDateLabel = 'Credit Note Date',
}: CreditNotePaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogo={companyLogo}
bigtitle={'Credit Note'}
>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showCreditNoteNumber && (
<PaperTemplate.TermsItem label={creditNoteNumberLabel}>
{creditNoteNumebr}
</PaperTemplate.TermsItem>
)}
{showCreditNoteDate && (
<PaperTemplate.TermsItem label={creditNoteDateLabel}>
{creditNoteDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
<Group spacing={10}>
<PaperTemplate.Address items={billedToAddress} />
<PaperTemplate.Address items={billedFromAddress} />
</Group>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: 'Item', accessor: 'item' },
{ label: 'Description', accessor: 'item' },
{ label: 'Rate', accessor: 'rate' },
{ label: 'Total', accessor: 'total' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
/>
)}
{showTotal && (
<PaperTemplate.TotalLine label={totalLabel} amount={total} />
)}
</PaperTemplate.Totals>
</Stack>
<Stack spacing={0}>
{showCustomerNote && (
<PaperTemplate.Statement label={customerNoteLabel}>
{customerNote}
</PaperTemplate.Statement>
)}
{showTermsConditions && (
<PaperTemplate.Statement label={termsConditionsLabel}>
{termsConditions}
</PaperTemplate.Statement>
)}
</Stack>
</Stack>
</PaperTemplate>
);
}

View File

@@ -4,6 +4,7 @@ import { Classes } from '@blueprintjs/core';
import { ElementCustomize } from '../../../ElementCustomize/ElementCustomize';
import { EstimateCustomizeGeneralField } from './EstimateCustomizeFieldsGeneral';
import { EstimateCustomizeContentFields } from './EstimateCustomizeFieldsContent';
import { EstimatePaperTemplate } from './EstimatePaperTemplate';
import { EstimateCustomizeValues } from './types';
import { initialValues } from './constants';
@@ -16,9 +17,9 @@ export default function EstimateCustomizeContent() {
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
{/* <ElementCustomize.PaperTemplate>
<InvoicePaperTemplate />
</ElementCustomize.PaperTemplate> */}
<ElementCustomize.PaperTemplate>
<EstimatePaperTemplate />
</ElementCustomize.PaperTemplate>
<ElementCustomize.FieldsTab id={'general'} label={'General'}>
<EstimateCustomizeGeneralField />

View File

@@ -0,0 +1,175 @@
import { Group, Stack } from '@/components';
import { PaperTemplate, PaperTemplateProps } from '../../Invoices/InvoiceCustomize/PaperTemplate';
export interface EstimatePaperTemplateProps extends PaperTemplateProps {
billedToAddress?: Array<string>;
billedFromAddress?: Array<string>;
total?: string;
showTotal?: boolean;
totalLabel?: string;
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
showCustomerNote?: boolean;
customerNote?: string;
customerNoteLabel?: string;
showTermsConditions?: boolean;
termsConditions?: string;
termsConditionsLabel?: string;
lines?: Array<{
item: string;
description: string;
rate: string;
quantity: string;
total: string;
}>;
expirationDate?: string;
showExpirationDate?: boolean;
expirationDateLabel?: string;
estimateDateLabel?: string;
showEstimateDate?: boolean;
estimateDate?: string;
estimateNumebr?: string;
estimateNumberLabel?: string;
showEstimateNumber?: boolean;
}
export function EstimatePaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo = true,
companyLogo,
billedToAddress = [
'Bigcapital Technology, Inc.',
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
billedFromAddress = [
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
showCustomerNote = true,
customerNote = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
customerNoteLabel = 'Customer Note',
showTermsConditions = true,
termsConditions = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
termsConditionsLabel = 'Terms & Conditions',
lines = [
{
item: 'Simply dummy text',
description: 'Simply dummy text of the printing and typesetting',
rate: '1',
quantity: '1000',
total: '$1000.00',
},
],
showEstimateNumber = true,
estimateNumberLabel = 'Estimate Number',
estimateNumebr = '346D3D40-0001',
estimateDate = 'September 3, 2024',
showEstimateDate = true,
estimateDateLabel = 'Estimate Date',
expirationDateLabel = 'Expiration Date',
showExpirationDate = true,
expirationDate = 'September 3, 2024',
}: EstimatePaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogo={companyLogo}
bigtitle={'Estimate'}
>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showEstimateNumber && (
<PaperTemplate.TermsItem label={estimateNumberLabel}>
{estimateNumebr}
</PaperTemplate.TermsItem>
)}
{showEstimateDate && (
<PaperTemplate.TermsItem label={estimateDateLabel}>
{estimateDate}
</PaperTemplate.TermsItem>
)}
{showExpirationDate && (
<PaperTemplate.TermsItem label={expirationDateLabel}>
{expirationDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
<Group spacing={10}>
<PaperTemplate.Address items={billedToAddress} />
<PaperTemplate.Address items={billedFromAddress} />
</Group>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: 'Item', accessor: 'item' },
{ label: 'Description', accessor: 'item' },
{ label: 'Rate', accessor: 'rate' },
{ label: 'Total', accessor: 'total' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
/>
)}
{showTotal && (
<PaperTemplate.TotalLine label={totalLabel} amount={total} />
)}
</PaperTemplate.Totals>
</Stack>
<Stack spacing={0}>
{showCustomerNote && (
<PaperTemplate.Statement label={customerNoteLabel}>
{customerNote}
</PaperTemplate.Statement>
)}
{showTermsConditions && (
<PaperTemplate.Statement label={termsConditionsLabel}>
{termsConditions}
</PaperTemplate.Statement>
)}
</Stack>
</Stack>
</PaperTemplate>
);
}

View File

@@ -0,0 +1,139 @@
import React from 'react';
import clsx from 'classnames';
import { get } from 'lodash';
import { Stack } from '@/components';
import styles from './InvoicePaperTemplate.module.scss';
export interface PaperTemplateProps {
primaryColor?: string;
secondaryColor?: string;
showCompanyLogo?: boolean;
companyLogo?: string;
bigtitle?: string;
children?: React.ReactNode;
}
export function PaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo,
companyLogo,
bigtitle = 'Invoice',
children,
}: PaperTemplateProps) {
return (
<div className={styles.root}>
<style>{`:root { --invoice-primary-color: ${primaryColor}; --invoice-secondary-color: ${secondaryColor}; }`}</style>
<div>
<h1 className={styles.bigTitle}>{bigtitle}</h1>
{showCompanyLogo && (
<div className={styles.logoWrap}>
<img alt="" src={companyLogo} />
</div>
)}
</div>
{children}
</div>
);
}
interface PaperTemplateTableProps {
columns: Array<{ accessor: string; label: string }>;
data: Array<Record<string, any>>;
}
PaperTemplate.Table = ({ columns, data }: PaperTemplateTableProps) => {
return (
<table className={styles.table}>
<thead>
<tr>
{columns.map((col, index) => (
<th key={index}>{col.label}</th>
))}
</tr>
</thead>
<tbody className={styles.tableBody}>
{data.map((_data: any) => (
<tr>
{columns.map((column, index) => (
<td key={index}>{get(_data, column.accessor)}</td>
))}
</tr>
))}
</tbody>
</table>
);
};
PaperTemplate.Totals = ({ children }: { children: React.ReactNode }) => {
return <div className={styles.totals}>{children}</div>;
};
PaperTemplate.TotalLine = ({
label,
amount,
}: {
label: string;
amount: string;
}) => {
return (
<div className={clsx(styles.totalsItem, styles.totalBottomGrayBordered)}>
<div className={styles.totalsItemLabel}>{label}</div>
<div className={styles.totalsItemAmount}>{amount}</div>
</div>
);
};
PaperTemplate.MutedText = () => {};
PaperTemplate.Text = () => {};
PaperTemplate.Address = ({ items }: { items: Array<string> }) => {
return (
<Stack spacing={0}>
{items.map((item, index) => (
<div key={index}>{item}</div>
))}
</Stack>
);
};
PaperTemplate.Statement = ({
label,
children,
}: {
label: string;
children: React.ReactNode;
}) => {
return (
<div className={styles.paragraph}>
{label && <div className={styles.paragraphLabel}>{label}</div>}
<div>{children}</div>
</div>
);
};
PaperTemplate.TermsList = ({ children }: { children: React.ReactNode }) => {
return <div className={styles.details}>{children}</div>;
};
PaperTemplate.TermsItem = ({
label,
children,
}: {
label: string;
children: React.ReactNode;
}) => {
return (
<div className={styles.detail}>
<div className={styles.detailLabel}>{label}</div>
<div>{children}</div>
</div>
);
};

View File

@@ -5,6 +5,7 @@ import { ElementCustomize } from '../../../ElementCustomize/ElementCustomize';
import { PaymentReceivedCustomizeGeneralField } from './PaymentReceivedCustomizeFieldsGeneral';
import { PaymentReceivedCustomizeContentFields } from './PaymentReceivedCustomizeFieldsContent';
import { PaymentReceivedCustomizeValues } from './types';
import { PaymentReceivedPaperTemplate } from './PaymentReceivedPaperTemplate';
import { initialValues } from './constants';
export default function PaymentReceivedCustomizeContent() {
@@ -16,9 +17,9 @@ export default function PaymentReceivedCustomizeContent() {
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
{/* <ElementCustomize.PaperTemplate>
<InvoicePaperTemplate />
</ElementCustomize.PaperTemplate> */}
<ElementCustomize.PaperTemplate>
<PaymentReceivedPaperTemplate />
</ElementCustomize.PaperTemplate>
<ElementCustomize.FieldsTab id={'general'} label={'General'}>
<PaymentReceivedCustomizeGeneralField />

View File

@@ -0,0 +1,127 @@
import { Group, Stack } from '@/components';
import { PaperTemplate, PaperTemplateProps } from '../../Invoices/InvoiceCustomize/PaperTemplate';
export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps {
billedToAddress?: Array<string>;
billedFromAddress?: Array<string>;
total?: string;
showTotal?: boolean;
totalLabel?: string;
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
lines?: Array<{
paidAmount: string;
invoiceAmount: string;
invoiceNumber: string;
}>;
paymentReceivedDateLabel?: string;
showPaymentReceivedDate?: boolean;
paymentReceivedDate?: string;
paymentReceivedNumebr?: string;
paymentReceivedNumberLabel?: string;
showPaymentReceivedNumber?: boolean;
}
export function PaymentReceivedPaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo = true,
companyLogo,
billedToAddress = [
'Bigcapital Technology, Inc.',
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
billedFromAddress = [
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
lines = [
{
invoiceNumber: 'INV-00001',
invoiceAmount: '$1000.00',
paidAmount: '$1000.00',
},
],
showPaymentReceivedNumber = true,
paymentReceivedNumberLabel = 'Payment Number',
paymentReceivedNumebr = '346D3D40-0001',
paymentReceivedDate = 'September 3, 2024',
showPaymentReceivedDate = true,
paymentReceivedDateLabel = 'Payment Date',
}: PaymentReceivedPaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogo={companyLogo}
bigtitle={'Payment'}
>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showPaymentReceivedNumber && (
<PaperTemplate.TermsItem label={paymentReceivedNumberLabel}>
{paymentReceivedNumebr}
</PaperTemplate.TermsItem>
)}
{showPaymentReceivedDate && (
<PaperTemplate.TermsItem label={paymentReceivedDateLabel}>
{paymentReceivedDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
<Group spacing={10}>
<PaperTemplate.Address items={billedToAddress} />
<PaperTemplate.Address items={billedFromAddress} />
</Group>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: 'Invoice #', accessor: 'invoiceNumber' },
{ label: 'Invoice Amount', accessor: 'invoiceAmount' },
{ label: 'Paid Amount', accessor: 'paidAmount' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
/>
)}
{showTotal && (
<PaperTemplate.TotalLine label={totalLabel} amount={total} />
)}
</PaperTemplate.Totals>
</Stack>
</Stack>
</PaperTemplate>
);
}

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { Box } from '@/components';
import { Classes } from '@blueprintjs/core';
import { ElementCustomize } from '../../../ElementCustomize/ElementCustomize';
import { ReceiptCustomizeGeneralField } from './ReceiptCustomizeFieldsGeneral';
import { ReceiptCustomizeFieldsContent } from './ReceiptCustomizeFieldsContent';
import { ReceiptPaperTemplate } from './ReceiptPaperTemplate';
import { ReceiptCustomizeValues } from './types';
import { initialValues } from './constants';
@@ -16,9 +16,9 @@ export default function ReceiptCustomizeContent() {
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
{/* <ElementCustomize.PaperTemplate>
<InvoicePaperTemplate />
</ElementCustomize.PaperTemplate> */}
<ElementCustomize.PaperTemplate>
<ReceiptPaperTemplate />
</ElementCustomize.PaperTemplate>
<ElementCustomize.FieldsTab id={'general'} label={'General'}>
<ReceiptCustomizeGeneralField />

View File

@@ -0,0 +1,161 @@
import { Group, Stack } from '@/components';
import { PaperTemplate, PaperTemplateProps } from '../../Invoices/InvoiceCustomize/PaperTemplate';
export interface ReceiptPaperTemplateProps extends PaperTemplateProps {
billedToAddress?: Array<string>;
billedFromAddress?: Array<string>;
total?: string;
showTotal?: boolean;
totalLabel?: string;
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
showCustomerNote?: boolean;
customerNote?: string;
customerNoteLabel?: string;
showTermsConditions?: boolean;
termsConditions?: string;
termsConditionsLabel?: string;
lines?: Array<{
item: string;
description: string;
rate: string;
quantity: string;
total: string;
}>;
receiptDateLabel?: string;
showReceiptDate?: boolean;
receiptDate?: string;
receiptNumebr?: string;
receiptNumberLabel?: string;
showReceiptNumber?: boolean;
}
export function ReceiptPaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo = true,
companyLogo,
billedToAddress = [
'Bigcapital Technology, Inc.',
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
billedFromAddress = [
'131 Continental Dr Suite 305 Newark,',
'Delaware 19713',
'United States',
'+1 762-339-5634',
'ahmed@bigcapital.app',
],
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
showCustomerNote = true,
customerNote = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
customerNoteLabel = 'Customer Note',
showTermsConditions = true,
termsConditions = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
termsConditionsLabel = 'Terms & Conditions',
lines = [
{
item: 'Simply dummy text',
description: 'Simply dummy text of the printing and typesetting',
rate: '1',
quantity: '1000',
total: '$1000.00',
},
],
showReceiptNumber = true,
receiptNumberLabel = 'Receipt Number',
receiptNumebr = '346D3D40-0001',
receiptDate = 'September 3, 2024',
showReceiptDate = true,
receiptDateLabel = 'Receipt Date',
}: ReceiptPaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogo={companyLogo}
bigtitle={'Receipt'}
>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showReceiptNumber && (
<PaperTemplate.TermsItem label={receiptNumberLabel}>
{receiptNumebr}
</PaperTemplate.TermsItem>
)}
{showReceiptDate && (
<PaperTemplate.TermsItem label={receiptDateLabel}>
{receiptDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
<Group spacing={10}>
<PaperTemplate.Address items={billedToAddress} />
<PaperTemplate.Address items={billedFromAddress} />
</Group>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: 'Item', accessor: 'item' },
{ label: 'Description', accessor: 'item' },
{ label: 'Rate', accessor: 'rate' },
{ label: 'Total', accessor: 'total' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
/>
)}
{showTotal && (
<PaperTemplate.TotalLine label={totalLabel} amount={total} />
)}
</PaperTemplate.Totals>
</Stack>
<Stack spacing={0}>
{showCustomerNote && (
<PaperTemplate.Statement label={customerNoteLabel}>
{customerNote}
</PaperTemplate.Statement>
)}
{showTermsConditions && (
<PaperTemplate.Statement label={termsConditionsLabel}>
{termsConditions}
</PaperTemplate.Statement>
)}
</Stack>
</Stack>
</PaperTemplate>
);
}