feat: estimate, receipt, credit note mail preview

This commit is contained in:
Ahmed Bouhuolia
2024-11-17 15:45:55 +02:00
parent d115ebde12
commit 53ab40a075
37 changed files with 1531 additions and 396 deletions

View File

@@ -0,0 +1,247 @@
import { Box } from '../lib/layout/Box';
import { Text } from '../lib/text/Text';
import { Stack } from '../lib/layout/Stack';
import { Group } from '../lib/layout/Group';
import {
DefaultPdfTemplateTerms,
DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from './_constants';
import { PaperTemplate, PaperTemplateProps } from './PaperTemplate';
export interface EstimatePaperTemplateProps extends PaperTemplateProps {
// # Company
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Estimate number
estimateNumebr?: string;
estimateNumberLabel?: string;
showEstimateNumber?: boolean;
// # Expiration date
expirationDate?: string;
showExpirationDate?: boolean;
expirationDateLabel?: string;
// # Estimate date
estimateDateLabel?: string;
showEstimateDate?: boolean;
estimateDate?: string;
// # Customer name
companyName?: string;
// Address
showCustomerAddress?: boolean;
customerAddress?: string;
showCompanyAddress?: boolean;
companyAddress?: string;
billedToLabel?: string;
// Totals
total?: string;
showTotal?: boolean;
totalLabel?: string;
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
// # Statements
showCustomerNote?: boolean;
customerNote?: string;
customerNoteLabel?: string;
// # Terms & conditions
showTermsConditions?: boolean;
termsConditions?: string;
termsConditionsLabel?: string;
lines?: Array<{
item: string;
description: string;
rate: string;
quantity: string;
total: string;
}>;
// Lines
lineItemLabel?: string;
lineQuantityLabel?: string;
lineRateLabel?: string;
lineTotalLabel?: string;
}
export function EstimatePaperTemplate({
primaryColor,
secondaryColor,
// # Company logo
showCompanyLogo = true,
companyLogoUri = '',
companyName,
// # Company address
companyAddress = DefaultPdfTemplateAddressBilledFrom,
showCompanyAddress = true,
// # Customer address
customerAddress = DefaultPdfTemplateAddressBilledTo,
showCustomerAddress = true,
billedToLabel = 'Billed To',
// # Total
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
// # Subtotal
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
// # Customer Note
showCustomerNote = true,
customerNote = DefaultPdfTemplateStatement,
customerNoteLabel = 'Customer Note',
// # Terms & Conditions
showTermsConditions = true,
termsConditions = DefaultPdfTemplateTerms,
termsConditionsLabel = 'Terms & Conditions',
lines = [
{
item: DefaultPdfTemplateItemName,
description: DefaultPdfTemplateItemDescription,
rate: '1',
quantity: '1000',
total: '$1000.00',
},
],
// Estimate number
showEstimateNumber = true,
estimateNumberLabel = 'Estimate Number',
estimateNumebr = '346D3D40-0001',
// Estimate date
estimateDate = 'September 3, 2024',
showEstimateDate = true,
estimateDateLabel = 'Estimate Date',
// Expiration date
expirationDateLabel = 'Expiration Date',
showExpirationDate = true,
expirationDate = 'September 3, 2024',
// Entries
lineItemLabel = 'Item',
lineQuantityLabel = 'Qty',
lineRateLabel = 'Rate',
lineTotalLabel = 'Total',
}: EstimatePaperTemplateProps) {
return (
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<Group align={'start'} spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Estimate'} />
<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>
</Stack>
{companyLogoUri && showCompanyLogo && (
<PaperTemplate.Logo logoUri={companyLogoUri} />
)}
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (
<PaperTemplate.Address>
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
</PaperTemplate.Address>
)}
{showCustomerAddress && (
<PaperTemplate.Address>
<strong>{billedToLabel}</strong>
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
</PaperTemplate.Address>
)}
</PaperTemplate.AddressesGroup>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{
label: lineItemLabel,
accessor: (data) => (
<Stack spacing={2}>
<Text>{data.item}</Text>
<Text
fontSize={'12px'}
// className={Classes.TEXT_MUTED}
// style={{ fontSize: 12 }}
>
{data.description}
</Text>
</Stack>
),
},
{ label: lineQuantityLabel, accessor: 'quantity' },
{ label: lineRateLabel, accessor: 'rate', align: 'right' },
{ label: lineTotalLabel, accessor: 'total', align: 'right' },
]}
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,180 @@
import { Box } from '../lib/layout/Box';
import { Stack } from '../lib/layout/Stack';
import { Group } from '../lib/layout/Group';
import {
PaperTemplate,
PaperTemplateProps,
PaperTemplateTotalBorder,
} from './PaperTemplate';
import {
DefaultPdfTemplateAddressBilledFrom,
DefaultPdfTemplateAddressBilledTo,
} from './_constants';
export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps {
// # Company logo
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Company name
companyName?: string;
// Customer address
showCustomerAddress?: boolean;
customerAddress?: string;
// Company address
showCompanyAddress?: boolean;
companyAddress?: string;
billedToLabel?: string;
// Total.
total?: string;
showTotal?: boolean;
totalLabel?: string;
// Subtotal.
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
lines?: Array<{
paidAmount: string;
invoiceAmount: string;
invoiceNumber: string;
}>;
// Issue date.
paymentReceivedDateLabel?: string;
showPaymentReceivedDate?: boolean;
paymentReceivedDate?: string;
// Payment received number.
paymentReceivedNumebr?: string;
paymentReceivedNumberLabel?: string;
showPaymentReceivedNumber?: boolean;
}
export function PaymentReceivedPaperTemplate({
// # Colors
primaryColor,
secondaryColor,
// # Company logo
showCompanyLogo = true,
companyLogoUri,
// # Company name
companyName = 'Bigcapital Technology, Inc.',
// # Customer address
showCustomerAddress = true,
customerAddress = DefaultPdfTemplateAddressBilledTo,
// # Company address
showCompanyAddress = true,
companyAddress = DefaultPdfTemplateAddressBilledFrom,
billedToLabel = 'Billed To',
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}>
<Stack spacing={24}>
<Group align={'start'} spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Payment'} />
<PaperTemplate.TermsList>
{showPaymentReceivedNumber && (
<PaperTemplate.TermsItem label={paymentReceivedNumberLabel}>
{paymentReceivedNumebr}
</PaperTemplate.TermsItem>
)}
{showPaymentReceivedDate && (
<PaperTemplate.TermsItem label={paymentReceivedDateLabel}>
{paymentReceivedDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Stack>
{companyLogoUri && showCompanyLogo && (
<PaperTemplate.Logo logoUri={companyLogoUri} />
)}
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (
<PaperTemplate.Address>
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
</PaperTemplate.Address>
)}
{showCustomerAddress && (
<PaperTemplate.Address>
<strong>{billedToLabel}</strong>
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
</PaperTemplate.Address>
)}
</PaperTemplate.AddressesGroup>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: 'Invoice #', accessor: 'invoiceNumber' },
{
label: 'Invoice Amount',
accessor: 'invoiceAmount',
align: 'right',
},
{ label: 'Paid Amount', accessor: 'paidAmount', align: 'right' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
border={PaperTemplateTotalBorder.Gray}
/>
)}
{showTotal && (
<PaperTemplate.TotalLine
label={totalLabel}
amount={total}
border={PaperTemplateTotalBorder.Dark}
style={{ fontWeight: 500 }}
/>
)}
</PaperTemplate.Totals>
</Stack>
</Stack>
</PaperTemplate>
);
}

View File

@@ -0,0 +1,237 @@
import { Box } from '../lib/layout/Box';
import { Text } from '../lib/text/Text';
import { Stack } from '../lib/layout/Stack';
import { Group } from '../lib/layout/Group';
import {
PaperTemplate,
PaperTemplateProps,
} from './PaperTemplate';
import {
DefaultPdfTemplateTerms,
DefaultPdfTemplateItemDescription,
DefaultPdfTemplateStatement,
DefaultPdfTemplateItemName,
DefaultPdfTemplateAddressBilledTo,
DefaultPdfTemplateAddressBilledFrom,
} from './_constants';
export interface ReceiptPaperTemplateProps extends PaperTemplateProps {
// # Company logo
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Company name
companyName?: string;
// Addresses
showCustomerAddress?: boolean;
customerAddress?: string;
showCompanyAddress?: boolean;
companyAddress?: string;
billedToLabel?: string;
// Total
total?: string;
showTotal?: boolean;
totalLabel?: string;
// Subtotal
subtotal?: string;
showSubtotal?: boolean;
subtotalLabel?: string;
// Customer Note
showCustomerNote?: boolean;
customerNote?: string;
customerNoteLabel?: string;
// Terms & Conditions
showTermsConditions?: boolean;
termsConditions?: string;
termsConditionsLabel?: string;
// Lines
lines?: Array<{
item: string;
description: string;
rate: string;
quantity: string;
total: string;
}>;
// Receipt Date.
receiptDateLabel?: string;
showReceiptDate?: boolean;
receiptDate?: string;
// Receipt Number
receiptNumebr?: string;
receiptNumberLabel?: string;
showReceiptNumber?: boolean;
// Entries
lineItemLabel?: string;
lineQuantityLabel?: string;
lineRateLabel?: string;
lineTotalLabel?: string;
}
export function ReceiptPaperTemplate({
// # Colors
primaryColor,
secondaryColor,
// # Company logo
showCompanyLogo = true,
companyLogoUri,
// # Company name
companyName = 'Bigcapital Technology, Inc.',
// # Address
showCustomerAddress = true,
customerAddress = DefaultPdfTemplateAddressBilledTo,
showCompanyAddress = true,
companyAddress = DefaultPdfTemplateAddressBilledFrom,
billedToLabel = 'Billed To',
total = '$1000.00',
totalLabel = 'Total',
showTotal = true,
subtotal = '1000/00',
subtotalLabel = 'Subtotal',
showSubtotal = true,
showCustomerNote = true,
customerNoteLabel = 'Customer Note',
customerNote = DefaultPdfTemplateStatement,
showTermsConditions = true,
termsConditionsLabel = 'Terms & Conditions',
termsConditions = DefaultPdfTemplateTerms,
lines = [
{
item: DefaultPdfTemplateItemName,
description: DefaultPdfTemplateItemDescription,
rate: '1',
quantity: '1000',
total: '$1000.00',
},
],
// Receipt Number
showReceiptNumber = true,
receiptNumberLabel = 'Receipt Number',
receiptNumebr = '346D3D40-0001',
// Receipt Date
receiptDate = 'September 3, 2024',
showReceiptDate = true,
receiptDateLabel = 'Receipt Date',
// Entries
lineItemLabel = 'Item',
lineQuantityLabel = 'Qty',
lineRateLabel = 'Rate',
lineTotalLabel = 'Total',
}: ReceiptPaperTemplateProps) {
return (
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<Group align={'start'} spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Receipt'} />
<PaperTemplate.TermsList>
{showReceiptNumber && (
<PaperTemplate.TermsItem label={receiptNumberLabel}>
{receiptNumebr}
</PaperTemplate.TermsItem>
)}
{showReceiptDate && (
<PaperTemplate.TermsItem label={receiptDateLabel}>
{receiptDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Stack>
{companyLogoUri && showCompanyLogo && (
<PaperTemplate.Logo logoUri={companyLogoUri} />
)}
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (
<PaperTemplate.Address>
<Box dangerouslySetInnerHTML={{ __html: companyAddress }} />
</PaperTemplate.Address>
)}
{showCustomerAddress && (
<PaperTemplate.Address>
<strong>{billedToLabel}</strong>
<Box dangerouslySetInnerHTML={{ __html: customerAddress }} />
</PaperTemplate.Address>
)}
</PaperTemplate.AddressesGroup>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{
label: lineItemLabel,
accessor: (data) => (
<Stack spacing={2}>
<Text>{data.item}</Text>
<Text
fontSize={'12px'}
// className={Classes.TEXT_MUTED}
// style={{ fontSize: 12 }}
>
{data.description}
</Text>
</Stack>
),
},
{ label: lineQuantityLabel, accessor: 'quantity' },
{ label: lineRateLabel, accessor: 'rate', align: 'right' },
{ label: lineTotalLabel, accessor: 'total', align: 'right' },
]}
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>
);
}