mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat: invoice customize paper preview
This commit is contained in:
@@ -1,60 +1,127 @@
|
||||
import clsx from 'classnames';
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import styles from './InvoicePaperTemplate.module.scss';
|
||||
|
||||
interface PapaerLine {
|
||||
item?: string;
|
||||
description?: string;
|
||||
quantity?: string;
|
||||
rate?: string;
|
||||
total?: string;
|
||||
}
|
||||
|
||||
interface PaperTax {
|
||||
label: string;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
interface PaperTemplateProps {
|
||||
primaryColor?: string;
|
||||
secondaryColor?: string;
|
||||
|
||||
showCompanyLogo?: boolean;
|
||||
companyLogo?: string;
|
||||
|
||||
showInvoiceNumber?: boolean;
|
||||
invoiceNumber?: string;
|
||||
invoiceNumberLabel?: string;
|
||||
|
||||
showDateIssue?: boolean;
|
||||
dateIssue?: string;
|
||||
dateIssueLabel?: string;
|
||||
|
||||
showDueDate?: boolean;
|
||||
dueDate?: string;
|
||||
dueDateLabel?: string;
|
||||
|
||||
companyName?: string;
|
||||
|
||||
bigtitle?: string;
|
||||
|
||||
itemRateLabel?: string;
|
||||
itemQuantityLabel?: string;
|
||||
itemTotalLabel?: string;
|
||||
// Address
|
||||
showBillingToAddress?: boolean;
|
||||
showBilledFromAddress?: boolean;
|
||||
billedToLabel?: string;
|
||||
|
||||
// Entries
|
||||
lineItemLabel?: string;
|
||||
lineDescriptionLabel?: string;
|
||||
lineRateLabel?: string;
|
||||
lineTotalLabel?: string;
|
||||
|
||||
// Totals
|
||||
showDueAmount?: boolean;
|
||||
showDiscount?: boolean;
|
||||
showPaymentMade?: boolean;
|
||||
showTaxes?: boolean;
|
||||
showSubtotal?: boolean;
|
||||
showTotal?: boolean;
|
||||
showBalanceDue?: boolean;
|
||||
|
||||
paymentMadeLabel?: string;
|
||||
discountLabel?: string;
|
||||
subtotalLabel?: string;
|
||||
totalLabel?: string;
|
||||
total?: string;
|
||||
|
||||
showDiscount?: boolean;
|
||||
discountLabel?: string;
|
||||
discount?: string;
|
||||
|
||||
showSubtotal?: boolean;
|
||||
subtotalLabel?: string;
|
||||
subtotal?: string;
|
||||
|
||||
showPaymentMade?: boolean;
|
||||
paymentMadeLabel?: string;
|
||||
paymentMade?: string;
|
||||
|
||||
showTaxes?: boolean;
|
||||
|
||||
showDueAmount?: boolean;
|
||||
showBalanceDue?: boolean;
|
||||
balanceDueLabel?: string;
|
||||
balanceDue?: string;
|
||||
|
||||
// Footer
|
||||
termsConditionsLabel: string;
|
||||
showTermsConditions: boolean;
|
||||
termsConditions: string;
|
||||
|
||||
statementLabel: string;
|
||||
showStatement: boolean;
|
||||
statement: string;
|
||||
|
||||
lines?: Array<PapaerLine>;
|
||||
taxes?: Array<PaperTax>;
|
||||
|
||||
billedFromAddres?: Array<string>;
|
||||
billedToAddress?: Array<string>;
|
||||
}
|
||||
|
||||
export function InvoicePaperTemplate({
|
||||
bigtitle = 'Invoice',
|
||||
function InvoicePaperTemplateRoot({
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
|
||||
bigtitle = 'Invoice',
|
||||
companyName = 'Bigcapital Technology, Inc.',
|
||||
// dueDateLabel,
|
||||
|
||||
showCompanyLogo = true,
|
||||
companyLogo,
|
||||
|
||||
dueDate = 'September 3, 2024',
|
||||
dueDateLabel = 'Date due',
|
||||
showDueDate,
|
||||
|
||||
dateIssue = 'September 3, 2024',
|
||||
dateIssueLabel = 'Date of issue',
|
||||
showDateIssue,
|
||||
|
||||
// dateIssue,
|
||||
invoiceNumberLabel = 'Invoice number',
|
||||
invoiceNumber = '346D3D40-0001',
|
||||
showInvoiceNumber,
|
||||
|
||||
// Address
|
||||
showBillingToAddress = true,
|
||||
showBilledFromAddress = true,
|
||||
billedToLabel = 'Billed To',
|
||||
|
||||
// Entries
|
||||
itemQuantityLabel = 'Quantity',
|
||||
itemRateLabel = 'Rate',
|
||||
itemTotalLabel = 'Total',
|
||||
lineItemLabel = 'Item',
|
||||
lineDescriptionLabel = 'Description',
|
||||
lineRateLabel = 'Rate',
|
||||
lineTotalLabel = 'Total',
|
||||
|
||||
totalLabel = 'Total',
|
||||
subtotalLabel = 'Subtotal',
|
||||
@@ -70,82 +137,127 @@ export function InvoicePaperTemplate({
|
||||
showPaymentMade = true,
|
||||
showDueAmount = true,
|
||||
showBalanceDue = true,
|
||||
|
||||
total = '$662.75',
|
||||
subtotal = '630.00',
|
||||
discount = '0.00',
|
||||
paymentMade = '100.00',
|
||||
balanceDue = '$562.75',
|
||||
|
||||
// Footer paragraphs.
|
||||
termsConditionsLabel = 'Terms & Conditions',
|
||||
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.',
|
||||
|
||||
lines = [
|
||||
{
|
||||
item: 'Simply dummy text',
|
||||
description: 'Simply dummy text of the printing and typesetting',
|
||||
rate: '1',
|
||||
quantity: '1000',
|
||||
total: '$1000.00',
|
||||
},
|
||||
],
|
||||
taxes = [
|
||||
{ label: 'Sample Tax1 (4.70%)', amount: '11.75' },
|
||||
{ label: 'Sample Tax2 (7.00%)', amount: '21.74' },
|
||||
],
|
||||
|
||||
statementLabel = 'Statement',
|
||||
showStatement = true,
|
||||
statement = 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
|
||||
billedToAddress = [
|
||||
'Bigcapital Technology, Inc.',
|
||||
'131 Continental Dr Suite 305 Newark,',
|
||||
'Delaware 19713',
|
||||
'United States',
|
||||
'+1 762-339-5634',
|
||||
'ahmed@bigcapital.app',
|
||||
],
|
||||
billedFromAddres = [
|
||||
'131 Continental Dr Suite 305 Newark,',
|
||||
'Delaware 19713',
|
||||
'United States',
|
||||
'+1 762-339-5634',
|
||||
'ahmed@bigcapital.app',
|
||||
],
|
||||
}: PaperTemplateProps) {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<style>{`:root { --invoice-primary-color: ${primaryColor}; --invoice-secondary-color: ${secondaryColor}; }`}</style>
|
||||
|
||||
<div>
|
||||
<h1 className={styles.bigTitle}>{bigtitle}</h1>
|
||||
<div className={styles.logoWrap}>
|
||||
<img
|
||||
alt=""
|
||||
src="https://cdn-development.mercury.com/demo-assets/avatars/mercury-demo-dark.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{showCompanyLogo && (
|
||||
<div className={styles.logoWrap}>
|
||||
<img alt="" src={companyLogo} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.details}>
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{invoiceNumberLabel}</div>
|
||||
<div>{invoiceNumber}</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{dateIssueLabel}</div>
|
||||
<div>{dateIssue}</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{dueDateLabel}</div>
|
||||
<div>{dueDate}</div>
|
||||
</div>
|
||||
{showInvoiceNumber && (
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{invoiceNumberLabel}</div>
|
||||
<div>{invoiceNumber}</div>
|
||||
</div>
|
||||
)}
|
||||
{showDateIssue && (
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{dateIssueLabel}</div>
|
||||
<div>{dateIssue}</div>
|
||||
</div>
|
||||
)}
|
||||
{showDueDate && (
|
||||
<div className={styles.detail}>
|
||||
<div className={styles.detailLabel}>{dueDateLabel}</div>
|
||||
<div>{dueDate}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.addressRoot}>
|
||||
<div className={styles.addressBillTo}>
|
||||
<strong>{companyName}</strong> <br />
|
||||
131 Continental Dr Suite 305 Newark,
|
||||
<br />
|
||||
Delaware 19713
|
||||
<br />
|
||||
United States
|
||||
<br />
|
||||
+1 762-339-5634
|
||||
<br />
|
||||
ahmed@bigcapital.app
|
||||
</div>
|
||||
{showBilledFromAddress && (
|
||||
<div className={styles.addressBillTo}>
|
||||
<strong>{companyName}</strong> <br />
|
||||
{billedFromAddres.map((text, index) => (
|
||||
<div key={index}>{text}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.addressFrom}>
|
||||
<strong>Billed To</strong> <br />
|
||||
Bigcapital Technology, Inc. <br />
|
||||
131 Continental Dr Suite 305 Newark,
|
||||
<br />
|
||||
Delaware 19713
|
||||
<br />
|
||||
United States
|
||||
<br />
|
||||
+1 762-339-5634
|
||||
<br />
|
||||
ahmed@bigcapital.app
|
||||
</div>
|
||||
{showBillingToAddress && (
|
||||
<div className={styles.addressFrom}>
|
||||
<strong>{billedToLabel}</strong> <br />
|
||||
{billedToAddress.map((text, index) => (
|
||||
<div key={index}>{text}</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<table className={styles.table}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item</th>
|
||||
<th>Description</th>
|
||||
<th className={styles.rate}>{itemRateLabel}</th>
|
||||
<th className={styles.total}>{itemTotalLabel}</th>
|
||||
<th>{lineItemLabel}</th>
|
||||
<th>{lineDescriptionLabel}</th>
|
||||
<th className={styles.rate}>{lineRateLabel}</th>
|
||||
<th className={styles.total}>{lineTotalLabel}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody className={styles.tableBody}>
|
||||
<tr>
|
||||
<td>Simply dummy text</td>
|
||||
<td>Simply dummy text of the printing and typesetting</td>
|
||||
<td className={styles.rate}>1 X $100,00</td>
|
||||
<td className={styles.total}>$100,00</td>
|
||||
</tr>
|
||||
{lines.map((line, index) => (
|
||||
<tr key={index}>
|
||||
<td>{line.item}</td>
|
||||
<td>{line.description}</td>
|
||||
<td className={styles.rate}>
|
||||
{line.quantity} X {line.rate}
|
||||
</td>
|
||||
<td className={styles.total}>{line.total}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -159,32 +271,25 @@ export function InvoicePaperTemplate({
|
||||
)}
|
||||
>
|
||||
<div className={styles.totalsItemLabel}>{subtotalLabel}</div>
|
||||
<div className={styles.totalsItemAmount}>630.00</div>
|
||||
<div className={styles.totalsItemAmount}>{subtotal}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showDiscount && (
|
||||
<div className={styles.totalsItem}>
|
||||
<div className={styles.totalsItemLabel}>{discountLabel}</div>
|
||||
<div className={styles.totalsItemAmount}>0.00</div>
|
||||
<div className={styles.totalsItemAmount}>{discount}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showTaxes && (
|
||||
<>
|
||||
<div className={styles.totalsItem}>
|
||||
<div className={styles.totalsItemLabel}>
|
||||
Sample Tax1 (4.70%)
|
||||
{taxes.map((tax, index) => (
|
||||
<div key={index} className={styles.totalsItem}>
|
||||
<div className={styles.totalsItemLabel}>{tax.label}</div>
|
||||
<div className={styles.totalsItemAmount}>{tax.amount}</div>
|
||||
</div>
|
||||
<div className={styles.totalsItemAmount}>11.75</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.totalsItem}>
|
||||
<div className={styles.totalsItemLabel}>
|
||||
Sample Tax2 (7.00%)
|
||||
</div>
|
||||
<div className={styles.totalsItemAmount}>21.00</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -193,14 +298,14 @@ export function InvoicePaperTemplate({
|
||||
className={clsx(styles.totalsItem, styles.totalBottomBordered)}
|
||||
>
|
||||
<div className={styles.totalsItemLabel}>{totalLabel}</div>
|
||||
<div className={styles.totalsItemAmount}>$662.75</div>
|
||||
<div className={styles.totalsItemAmount}>{total}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showPaymentMade && (
|
||||
<div className={styles.totalsItem}>
|
||||
<div className={styles.totalsItemLabel}>{paymentMadeLabel}</div>
|
||||
<div className={styles.totalsItemAmount}>100.00</div>
|
||||
<div className={styles.totalsItemAmount}>{paymentMade}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -209,27 +314,38 @@ export function InvoicePaperTemplate({
|
||||
className={clsx(styles.totalsItem, styles.totalBottomBordered)}
|
||||
>
|
||||
<div className={styles.totalsItemLabel}>{balanceDueLabel}</div>
|
||||
<div className={styles.totalsItemAmount}>$562.75</div>
|
||||
<div className={styles.totalsItemAmount}>{balanceDue}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.paragraph}>
|
||||
<div className={styles.paragraphLabel}>Terms & Conditions</div>
|
||||
<div>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
{showTermsConditions && (
|
||||
<div className={styles.paragraph}>
|
||||
<div className={styles.paragraphLabel}>{termsConditionsLabel}</div>
|
||||
<div>{termsConditions}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.paragraph}>
|
||||
<div className={styles.paragraphLabel}>Statement</div>
|
||||
<div>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
)}
|
||||
{showStatement && (
|
||||
<div className={styles.paragraph}>
|
||||
<div className={styles.paragraphLabel}>{statementLabel}</div>
|
||||
<div>{statement}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const withFormikProps = <P extends object>(
|
||||
Component: React.ComponentType<P>,
|
||||
) => {
|
||||
return (props: Omit<P, keyof PaperTemplateProps>) => {
|
||||
const { values } = useFormikContext<PaperTemplateProps>();
|
||||
|
||||
return <Component {...(props as P)} {...values} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoicePaperTemplate = R.compose(withFormikProps)(
|
||||
InvoicePaperTemplateRoot,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user