feat: paper template customize

This commit is contained in:
Ahmed Bouhuolia
2024-09-10 21:54:37 +02:00
parent 77a1e35ff4
commit 716dec799a
19 changed files with 269 additions and 293 deletions

View File

@@ -3,7 +3,6 @@ import { Classes, Text } from '@blueprintjs/core';
import { FFormGroup, FSwitch, Group, Stack } from '@/components';
import { FColorInput } from '@/components/Forms/FColorInput';
import { CreditCardIcon } from '@/icons/CreditCardIcon';
import styles from './InvoiceCustomizeFields.module.scss';
export function InvoiceCustomizeGeneralField() {
return (
@@ -20,7 +19,7 @@ export function InvoiceCustomizeGeneralField() {
<FFormGroup
name={'primaryColor'}
label={'Primary Color'}
className={styles.fieldGroup}
style={{ justifyContent: 'space-between' }}
inline
fastField
>
@@ -34,7 +33,7 @@ export function InvoiceCustomizeGeneralField() {
<FFormGroup
name={'secondaryColor'}
label={'Secondary Color'}
className={styles.fieldGroup}
style={{ justifyContent: 'space-between' }}
inline
fastField
>
@@ -49,7 +48,7 @@ export function InvoiceCustomizeGeneralField() {
<FSwitch
name={'showCompanyLogo'}
label={'Display company logo in the paper'}
className={styles.showCompanyLogoField}
style={{ fontSize: 14 }}
large
fastField
/>

View File

@@ -1,8 +1,11 @@
// @ts-nocheck
import { FInputGroup, FSwitch, Group, Stack } from '@/components';
import { CLASSES } from '@/constants';
import { Stack } from '@/components';
import { Classes } from '@blueprintjs/core';
import { fieldsGroups } from './constants';
import {
ElementCustomizeFieldsGroup,
ElementCustomizeContentItemFieldGroup,
} from '@/containers/ElementCustomize/ElementCustomizeFieldsGroup';
export function InvoiceCustomizeContentFields() {
return (
@@ -20,25 +23,20 @@ export function InvoiceCustomizeContentFields() {
<Stack>
{fieldsGroups.map((group) => (
<>
<h4 className={CLASSES.TEXT_MUTED} style={{ fontWeight: 600 }}>
{group.label}
</h4>
<Stack spacing={14}>
{group.fields.map((item, index) => (
<Group spacing={14} position={'apart'} key={index}>
<FSwitch name={item.enableKey} label={item.label} fastField />
{item.labelKey && (
<FInputGroup
name={item.labelKey}
style={{ maxWidth: 150 }}
fastField
/>
)}
</Group>
))}
</Stack>
</>
<ElementCustomizeFieldsGroup label={group.label}>
{group.fields.map((item, index) => (
<ElementCustomizeContentItemFieldGroup
key={index}
inputGroupProps={{
name: item.enableKey,
label: item.label,
}}
switchProps={{
name: item.labelKey,
}}
/>
))}
</ElementCustomizeFieldsGroup>
))}
</Stack>
</Stack>

View File

@@ -22,7 +22,6 @@
}
.details {
margin-bottom: 25px;
display: flex;
flex-direction: column;
gap: 4px;
@@ -40,7 +39,6 @@
.addressRoot{
display: flex;
flex-direction: row;
margin-bottom: 25px;
}
.addressBillTo{
@@ -101,7 +99,6 @@
.totals{
display: flex;
flex-direction: column;
margin-bottom: 40px;
margin-left: auto;
width: 300px;
}

View File

@@ -2,6 +2,9 @@ import clsx from 'classnames';
import * as R from 'ramda';
import { useFormikContext } from 'formik';
import styles from './InvoicePaperTemplate.module.scss';
import { PaperTemplate } from './PaperTemplate';
import { Group, Stack } from '@/components';
import React from 'react';
interface PapaerLine {
item?: string;
@@ -85,15 +88,14 @@ interface PaperTemplateProps {
lines?: Array<PapaerLine>;
taxes?: Array<PaperTax>;
billedFromAddres?: Array<string>;
billedToAddress?: Array<string>;
billedFromAddres?: Array<string | React.ReactNode>;
billedToAddress?: Array<string | React.ReactNode>;
}
function InvoicePaperTemplateRoot({
primaryColor,
secondaryColor,
bigtitle = 'Invoice',
companyName = 'Bigcapital Technology, Inc.',
showCompanyLogo = true,
@@ -183,156 +185,109 @@ function InvoicePaperTemplateRoot({
],
}: 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>
<div className={styles.details}>
{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}>
{showBilledFromAddress && (
<div className={styles.addressBillTo}>
<strong>{companyName}</strong> <br />
{billedFromAddres.map((text, index) => (
<div key={index}>{text}</div>
))}
</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>{lineItemLabel}</th>
<th>{lineDescriptionLabel}</th>
<th className={styles.rate}>{lineRateLabel}</th>
<th className={styles.total}>{lineTotalLabel}</th>
</tr>
</thead>
<tbody className={styles.tableBody}>
{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>
<div style={{ display: 'flex' }}>
<div className={styles.totals}>
{showSubtotal && (
<div
className={clsx(
styles.totalsItem,
styles.totalBottomGrayBordered,
)}
>
<div className={styles.totalsItemLabel}>{subtotalLabel}</div>
<div className={styles.totalsItemAmount}>{subtotal}</div>
</div>
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogo={companyLogo}
bigtitle={'Invoice'}
>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showInvoiceNumber && (
<PaperTemplate.TermsItem label={invoiceNumberLabel}>
{invoiceNumber}
</PaperTemplate.TermsItem>
)}
{showDiscount && (
<div className={styles.totalsItem}>
<div className={styles.totalsItemLabel}>{discountLabel}</div>
<div className={styles.totalsItemAmount}>{discount}</div>
</div>
{showDateIssue && (
<PaperTemplate.TermsItem label={dateIssueLabel}>
{dateIssue}
</PaperTemplate.TermsItem>
)}
{showTaxes && (
<>
{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>
))}
</>
{showDueDate && (
<PaperTemplate.TermsItem label={dueDateLabel}>
{dueDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
{showTotal && (
<div
className={clsx(styles.totalsItem, styles.totalBottomBordered)}
>
<div className={styles.totalsItemLabel}>{totalLabel}</div>
<div className={styles.totalsItemAmount}>{total}</div>
</div>
<Group spacing={10}>
{showBilledFromAddress && (
<PaperTemplate.Address
items={[<strong>{companyName}</strong>, ...billedFromAddres]}
/>
)}
{showPaymentMade && (
<div className={styles.totalsItem}>
<div className={styles.totalsItemLabel}>{paymentMadeLabel}</div>
<div className={styles.totalsItemAmount}>{paymentMade}</div>
</div>
{showBillingToAddress && (
<PaperTemplate.Address items={billedToAddress} />
)}
</Group>
{showBalanceDue && (
<div
className={clsx(styles.totalsItem, styles.totalBottomBordered)}
>
<div className={styles.totalsItemLabel}>{balanceDueLabel}</div>
<div className={styles.totalsItemAmount}>{balanceDue}</div>
</div>
<Stack spacing={0}>
<PaperTemplate.Table
columns={[
{ label: lineItemLabel, accessor: 'item' },
{ label: lineDescriptionLabel, accessor: 'description' },
{ label: lineRateLabel, accessor: 'rate' },
{ label: lineTotalLabel, accessor: 'total' },
]}
data={lines}
/>
<PaperTemplate.Totals>
{showSubtotal && (
<PaperTemplate.TotalLine
label={subtotalLabel}
amount={subtotal}
/>
)}
{showDiscount && (
<PaperTemplate.TotalLine
label={discountLabel}
amount={discount}
/>
)}
{showTaxes && (
<>
{taxes.map((tax, index) => (
<PaperTemplate.TotalLine
key={index}
label={tax.label}
amount={tax.amount}
/>
))}
</>
)}
{showTotal && (
<PaperTemplate.TotalLine label={totalLabel} amount={total} />
)}
{showPaymentMade && (
<PaperTemplate.TotalLine
label={paymentMadeLabel}
amount={paymentMade}
/>
)}
{showBalanceDue && (
<PaperTemplate.TotalLine
label={balanceDueLabel}
amount={balanceDue}
/>
)}
</PaperTemplate.Totals>
</Stack>
<Stack spacing={0}>
{showTermsConditions && (
<PaperTemplate.Statement label={termsConditionsLabel}>
{termsConditions}
</PaperTemplate.Statement>
)}
</div>
</div>
{showTermsConditions && (
<div className={styles.paragraph}>
<div className={styles.paragraphLabel}>{termsConditionsLabel}</div>
<div>{termsConditions}</div>
</div>
)}
{showStatement && (
<div className={styles.paragraph}>
<div className={styles.paragraphLabel}>{statementLabel}</div>
<div>{statement}</div>
</div>
)}
</div>
{showStatement && (
<PaperTemplate.Statement label={statementLabel}>
{statement}
</PaperTemplate.Statement>
)}
</Stack>
</Stack>
</PaperTemplate>
);
}

View File

@@ -94,7 +94,11 @@ PaperTemplate.MutedText = () => {};
PaperTemplate.Text = () => {};
PaperTemplate.Address = ({ items }: { items: Array<string> }) => {
PaperTemplate.Address = ({
items,
}: {
items: Array<string | React.ReactNode>;
}) => {
return (
<Stack spacing={0}>
{items.map((item, index) => (