feat: add discount and adjustment fields to email templates.

This commit is contained in:
Ahmed Bouhuolia
2024-12-03 13:20:01 +02:00
parent 154ade9647
commit d5dacaa988
16 changed files with 598 additions and 243 deletions

View File

@@ -30,4 +30,7 @@ If you have any questions, please let us know.
Thanks,
Bigcapital`,
subtotal: '$1,000.00',
discount: '$1,000.00',
adjustment: '$1,000.00'
};

View File

@@ -7,6 +7,7 @@ import {
Section,
Text,
} from '@react-email/components';
import isEmpty from 'lodash.isempty';
import { EmailTemplateLayout } from './EmailTemplateLayout';
import { CSSProperties } from 'react';
import { EmailTemplate } from './EmailTemplate';
@@ -25,6 +26,18 @@ export interface CreditNoteEmailProps {
total: string;
totalLabel?: string;
// # Subtotal
subtotal: string;
subtotalLabel?: string;
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Discount
discount?: string;
discountLabel?: string;
// # Items
items: Array<{ label: string; quantity: string; rate: string }>;
@@ -56,6 +69,18 @@ export const CreditNoteEmailTemplate: React.FC<
total,
totalLabel = 'Total',
// # Subtotal
subtotal,
subtotalLabel = 'Subtotal',
// # Discount
discount,
discountLabel = 'Discount',
// # Adjustment
adjustment,
adjustmentLabel = 'Adjustment',
// # Credit Note #
creditNoteNumberLabel = 'Credit Note # {creditNoteNumber}',
creditNoteNumber = 'CN-00001',
@@ -70,70 +95,104 @@ export const CreditNoteEmailTemplate: React.FC<
// # Items
items = [],
}) => {
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
<Section style={mainSectionStyle}>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
<Section style={mainSectionStyle}>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
<Section style={headerInfoStyle}>
<Row>
<Heading style={companyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={invoiceAmountStyle}>{total}</Text>
</Row>
<Row>
<Text style={creditNumberStyle}>
{creditNoteNumberLabel?.replace(
'{creditNoteNumber}',
creditNoteNumber
)}
</Text>
</Row>
</Section>
<Text style={messageStyle}>{message}</Text>
<Button
href={viewButtonUrl}
style={{
...viewInvoiceButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewButtonLabel}
</Button>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
</Column>
</Row>
</Section>
<Section style={headerInfoStyle}>
<Row>
<Heading style={companyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={invoiceAmountStyle}>{total}</Text>
</Row>
<Row>
<Text style={creditNumberStyle}>
{creditNoteNumberLabel?.replace(
'{creditNoteNumber}',
creditNoteNumber
)}
</Text>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
<Text style={messageStyle}>{message}</Text>
<Button
href={viewButtonUrl}
style={{
...viewInvoiceButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewButtonLabel}
</Button>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{subtotalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{subtotal}</Text>
</Column>
</Row>
{!isEmpty(discount) && (
<Row style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{discountLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>{discount}</Text>
</Column>
</Row>
)}
{!isEmpty(adjustment) && (
<Row style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{adjustmentLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>{adjustment}</Text>
</Column>
</Row>
)}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
</Column>
</Row>
</Section>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
/**
* Renders the estimate mail template to string

View File

@@ -30,4 +30,7 @@ If you have any questions, please let us know.
Thanks,
Bigcapital`,
adjustment: '$100.00',
discount: '$100.00',
subtotal: '$100.00',
};

View File

@@ -1,8 +1,8 @@
import { CSSProperties } from 'react';
import isEmpty from 'lodash.isempty';
import {
Button,
Column,
Container,
Heading,
render,
Row,
@@ -30,7 +30,15 @@ export interface EstimatePaymentEmailProps {
subtotal: string;
subtotalLabel?: string;
// # Estimate No#
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Discount
discount?: string;
discountLabel?: string;
// # Estimate No.
estimateNumber?: string;
estimateNumberLabel?: string;
@@ -65,6 +73,14 @@ export const EstimatePaymentEmail: React.FC<
total,
totalLabel = 'Total',
// # Adjustment
adjustment,
adjustmentLabel = 'Adjustment',
// # Discount
discount,
discountLabel = 'Discount',
// # Subtotal
subtotal,
subtotalLabel = 'Subtotal',
@@ -87,84 +103,108 @@ export const EstimatePaymentEmail: React.FC<
// # Items
items = [],
}) => {
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={estimateAmountStyle}>{total}</Text>
</Row>
<Row>
<Text style={estimateNumberStyle}>
{estimateNumberLabel?.replace('{estimateNumber}', estimateNumber)}
</Text>
</Row>
<Row>
<Text style={estimateExpirationStyle}>
{expirationDateLabel.replace('{expirationDate}', expirationDate)}
</Text>
</Row>
</Section>
<Text style={estimateMessageStyle}>{message}</Text>
<Button
href={viewEstimateButtonUrl}
style={{
...viewEstimateButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewEstimateButtonLabel}
</Button>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
<Row>
<Text style={estimateAmountStyle}>{total}</Text>
</Row>
<Row>
<Text style={estimateNumberStyle}>
{estimateNumberLabel?.replace('{estimateNumber}', estimateNumber)}
</Text>
</Row>
<Row>
<Text style={estimateExpirationStyle}>
{expirationDateLabel.replace('{expirationDate}', expirationDate)}
</Text>
</Row>
</Section>
))}
<Text style={estimateMessageStyle}>{message}</Text>
<Button
href={viewEstimateButtonUrl}
style={{
...viewEstimateButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewEstimateButtonLabel}
</Button>
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{subtotalLabel}</Text>
</Column>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{subtotal}</Text>
</Column>
</Row>
{!isEmpty(discount) && (
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{subtotalLabel}</Text>
<Text style={listItemLabelStyle}>{discountLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{subtotal}</Text>
<Text style={listItemAmountStyle}>{discount}</Text>
</Column>
</Row>
)}
{!isEmpty(adjustment) && (
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
<Text style={listItemLabelStyle}>{adjustmentLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
<Text style={listItemAmountStyle}>{adjustment}</Text>
</Column>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
)}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
</Column>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
/**
* Renders the estimate mail template to string
* @param {EstimatePaymentEmailProps} props
* @param {EstimatePaymentEmailProps} props
* @returns {Promise<string>}
*/
export const renderEstimateEmailTemplate = (

View File

@@ -33,6 +33,9 @@ Thanks,
Bigcapital`,
dueDate: ' 10 Oct 2024',
total: '$1,000.00',
subtotal: '$1,000.00',
dueAmount: '$1,000.00',
items: [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
adjustment: '$100.00',
discount: '$100.00',
};

View File

@@ -1,6 +1,6 @@
import { CSSProperties } from 'react';
import {
Button,
Container,
Section,
Heading,
Text,
@@ -8,7 +8,7 @@ import {
Column,
render,
} from '@react-email/components';
import { CSSProperties } from 'react';
import isEmpty from 'lodash.isempty';
import { EmailTemplateLayout } from './EmailTemplateLayout';
import { EmailTemplate } from './EmailTemplate';
@@ -36,6 +36,18 @@ export interface InvoicePaymentEmailProps {
dueAmount: string;
dueAmountLabel?: string;
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Discount
discount?: string;
discountLabel?: string;
// # Subtotal
subtotal: string;
subtotalLabel?: string;
// # Due date
dueDate: string;
dueDateLabel?: string;
@@ -82,6 +94,18 @@ export const InvoicePaymentEmail: React.FC<
total,
totalLabel = 'Total',
// # Subtotal
subtotal,
subtotalLabel = 'Subtotal',
// # Discount
discount,
discountLabel = 'Discount',
// # Adjustment
adjustment,
adjustmentLabel = 'Adjustment',
// # Invoice due amount
dueAmountLabel = 'Due Amount',
dueAmount,
@@ -92,84 +116,118 @@ export const InvoicePaymentEmail: React.FC<
items,
}) => {
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
<Section style={mainSectionStyle}>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
<Section style={mainSectionStyle}>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={invoiceAmountStyle}>{invoiceAmount}</Text>
</Row>
<Row>
<Text style={invoiceNumberStyle}>
{invoiceNumberLabel?.replace('{invoiceNumber}', invoiceNumber)}
</Text>
</Row>
<Row>
<Text style={invoiceDateStyle}>
{dueDateLabel.replace('{dueDate}', dueDate)}
</Text>
</Row>
</Section>
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={invoiceAmountStyle}>{invoiceAmount}</Text>
</Row>
<Row>
<Text style={invoiceNumberStyle}>
{invoiceNumberLabel?.replace('{invoiceNumber}', invoiceNumber)}
</Text>
</Row>
<Row>
<Text style={invoiceDateStyle}>
{dueDateLabel.replace('{dueDate}', dueDate)}
</Text>
</Row>
</Section>
<Text style={invoiceMessageStyle}>{invoiceMessage}</Text>
<Button
href={viewInvoiceButtonUrl}
style={{
...viewInvoiceButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewInvoiceButtonLabel}
</Button>
<Text style={invoiceMessageStyle}>{invoiceMessage}</Text>
<Button
href={viewInvoiceButtonUrl}
style={{
...viewInvoiceButtonStyle,
backgroundColor: primaryColor,
}}
>
{viewInvoiceButtonLabel}
</Button>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Row style={dueAmounLineRowStyle}>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={dueAmountLineItemLabelStyle}>
{dueAmountLabel}
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{subtotalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{subtotal}</Text>
</Column>
</Row>
{!isEmpty(discount) && (
<Row style={lineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{discountLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={dueAmountLineItemAmountStyle}>{dueAmount}</Text>
<Text style={listItemAmountStyle}>{discount}</Text>
</Column>
</Row>
)}
<Row style={totalLineRowStyle}>
{!isEmpty(adjustment) && (
<Row style={lineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
<Text style={listItemLabelStyle}>{adjustmentLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
<Text style={listItemAmountStyle}>{adjustment}</Text>
</Column>
</Row>
</Section>
)}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
</Column>
</Row>
<Row style={dueAmounLineRowStyle}>
<Column width={'50%'}>
<Text style={dueAmountLineItemLabelStyle}>
{dueAmountLabel}
</Text>
</Column>
<Column width={'50%'}>
<Text style={dueAmountLineItemAmountStyle}>{dueAmount}</Text>
</Column>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
export const renderInvoicePaymentEmail = (props: InvoicePaymentEmailProps) => {
return render(<InvoicePaymentEmail {...props} />);
@@ -237,6 +295,11 @@ const dueAmounLineRowStyle: CSSProperties = {
height: 40,
};
const lineRowStyle: CSSProperties = {
borderBottom: '1px solid #D9D9D9',
height: 40,
};
const totalLineRowStyle: CSSProperties = {
borderBottom: '1px solid #000',
height: 40,

View File

@@ -28,4 +28,6 @@ If you have any questions, please let us know.
Thanks,
Bigcapital`,
adjustment: '$100.00',
discount: '$100.00',
};

View File

@@ -1,5 +1,5 @@
import { CSSProperties } from 'react';
import {
Button,
Column,
Heading,
render,
@@ -7,14 +7,12 @@ import {
Section,
Text,
} from '@react-email/components';
import { CSSProperties } from 'react';
import isEmpty from 'lodash.isempty';
import { EmailTemplateLayout } from './EmailTemplateLayout';
import { EmailTemplate } from './EmailTemplate';
export interface ReceiptEmailTemplateProps {
preview: string;
companyName?: string;
companyLogoUri: string;
@@ -36,6 +34,10 @@ export interface ReceiptEmailTemplateProps {
discount?: string;
discountLabel?: string;
// # Adjustment
adjustment?: string;
adjustmentLabel?: string;
// # Subtotal
subtotal?: string;
subtotalLabel?: string;
@@ -60,6 +62,14 @@ export const ReceiptEmailTemplate: React.FC<
total = '$1,000.00',
totalLabel = 'Total',
// # Diso
discountLabel = 'Discount',
discount,
// # ADjustment
adjustmentLabel = 'Adjustment',
adjustment,
// # Subtotal
subtotal = '$1,000.00',
subtotalLabel = 'Subtotal',
@@ -74,68 +84,92 @@ export const ReceiptEmailTemplate: React.FC<
// # Items
items = [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
}) => {
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
return (
<EmailTemplateLayout preview={preview}>
<EmailTemplate>
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
</Row>
<Section style={headerInfoStyle}>
<Row>
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
</Row>
<Row>
<Text style={amountStyle}>{total}</Text>
</Row>
<Row>
<Text style={amountStyle}>{total}</Text>
</Row>
<Row>
<Text style={receiptNumberStyle}>
{receiptNumberLabel?.replace('{receiptNumber}', receiptNumber)}
</Text>
</Row>
</Section>
<Row>
<Text style={receiptNumberStyle}>
{receiptNumberLabel?.replace('{receiptNumber}', receiptNumber)}
</Text>
</Row>
</Section>
<Text style={messageStyle}>{message}</Text>
<Text style={messageStyle}>{message}</Text>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
))}
<Row style={totalLineRowStyle}>
<Section style={totalsSectionStyle}>
{items.map((item, index) => (
<Row key={index} style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={dueAmountLineItemLabelStyle}>{subtotalLabel}</Text>
<Text style={listItemLabelStyle}>{item.label}</Text>
</Column>
<Column width={'50%'}>
<Text style={dueAmountLineItemAmountStyle}>{subtotal}</Text>
<Text style={listItemAmountStyle}>
{item.quantity} x {item.rate}
</Text>
</Column>
</Row>
<Row style={totalLineRowStyle}>
))}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={dueAmountLineItemLabelStyle}>{subtotalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={dueAmountLineItemAmountStyle}>{subtotal}</Text>
</Column>
</Row>
{!isEmpty(discount) && (
<Row style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
<Text style={listItemLabelStyle}>{discountLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
<Text style={listItemAmountStyle}>{discount}</Text>
</Column>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
)}
{!isEmpty(adjustment) && (
<Row style={itemLineRowStyle}>
<Column width={'50%'}>
<Text style={listItemLabelStyle}>{adjustmentLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={listItemAmountStyle}>{adjustment}</Text>
</Column>
</Row>
)}
<Row style={totalLineRowStyle}>
<Column width={'50%'}>
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
</Column>
<Column width={'50%'}>
<Text style={totalLineItemAmountStyle}>{total}</Text>
</Column>
</Row>
</Section>
</EmailTemplate>
</EmailTemplateLayout>
);
};
/**
* Renders the sale receipt mail template to string