fix: Pdf templates layout

This commit is contained in:
Ahmed Bouhuolia
2024-10-05 19:01:34 +02:00
parent 90f08c5d51
commit af5726c48c
9 changed files with 184 additions and 145 deletions

View File

@@ -27,11 +27,14 @@ export interface GroupProps extends React.ComponentPropsWithoutRef<'div'> {
/** Defines align-items css property */
align?: React.CSSProperties['alignItems'];
flex?: React.CSSProperties['flex'];
}
const defaultProps: Partial<GroupProps> = {
position: 'left',
spacing: 20,
flex: 'none'
};
export function Group({ children, ...props }: GroupProps) {
@@ -48,6 +51,7 @@ const GroupStyled = styled(Box)`
box-sizing: border-box;
display: flex;
flex-direction: row;
flex: ${(props: GroupProps) => (props.flex)};
align-items: ${(props: GroupProps) => (props.align || 'center')};
flex-wrap: ${(props: GroupProps) => (props.noWrap ? 'nowrap' : 'wrap')};
justify-content: ${(props: GroupProps) =>

View File

@@ -11,12 +11,15 @@ export interface StackProps extends React.ComponentPropsWithoutRef<'div'> {
/** justify-content CSS property */
justify?: React.CSSProperties['justifyContent'];
flex?: React.CSSProperties['flex'];
}
const defaultProps: Partial<StackProps> = {
spacing: 20,
align: 'stretch',
justify: 'top',
flex: 'none',
};
export function Stack(props: StackProps) {
@@ -33,4 +36,5 @@ const StackStyled = styled(Box)`
align-items: ${(props: StackProps) => props.align};
justify-content: justify;
gap: ${(props: StackProps) => props.spacing}px;
flex: ${(props: StackProps) => props.flex};
`;

View File

@@ -1,4 +1,4 @@
import { Box, Stack } from '@/components';
import { Box, Group, Stack } from '@/components';
import {
PaperTemplate,
PaperTemplateProps,
@@ -13,6 +13,13 @@ import {
} from '@/constants/PdfTemplates';
export interface CreditNotePaperTemplateProps extends PaperTemplateProps {
// # Company logo
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Company name
companyName?: string;
// Address
showCustomerAddress?: boolean;
customerAddress?: string;
@@ -122,26 +129,30 @@ export function CreditNotePaperTemplate({
creditNoteDateLabel = 'Credit Note Date',
}: CreditNotePaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogoUri={companyLogoUri}
bigtitle={'Credit Note'}
>
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showCreditNoteNumber && (
<PaperTemplate.TermsItem label={creditNoteNumberLabel}>
{creditNoteNumebr}
</PaperTemplate.TermsItem>
<Group align={'start'} spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Credit Note'} />
<PaperTemplate.TermsList>
{showCreditNoteNumber && (
<PaperTemplate.TermsItem label={creditNoteNumberLabel}>
{creditNoteNumebr}
</PaperTemplate.TermsItem>
)}
{showCreditNoteDate && (
<PaperTemplate.TermsItem label={creditNoteDateLabel}>
{creditNoteDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Stack>
{companyLogoUri && showCompanyLogo && (
<PaperTemplate.Logo logoUri={companyLogoUri} />
)}
{showCreditNoteDate && (
<PaperTemplate.TermsItem label={creditNoteDateLabel}>
{creditNoteDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (

View File

@@ -1,4 +1,4 @@
import { Box, Stack } from '@/components';
import { Box, Group, Stack } from '@/components';
import {
PaperTemplate,
PaperTemplateProps,
@@ -13,6 +13,10 @@ import {
} from '@/constants/PdfTemplates';
export interface EstimatePaperTemplateProps extends PaperTemplateProps {
// # Company
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Estimate number
estimateNumebr?: string;
estimateNumberLabel?: string;
@@ -132,31 +136,35 @@ export function EstimatePaperTemplate({
expirationDate = 'September 3, 2024',
}: EstimatePaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogoUri={companyLogoUri}
bigtitle={'Estimate'}
>
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showEstimateNumber && (
<PaperTemplate.TermsItem label={estimateNumberLabel}>
{estimateNumebr}
</PaperTemplate.TermsItem>
<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} />
)}
{showEstimateDate && (
<PaperTemplate.TermsItem label={estimateDateLabel}>
{estimateDate}
</PaperTemplate.TermsItem>
)}
{showExpirationDate && (
<PaperTemplate.TermsItem label={expirationDateLabel}>
{expirationDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (

View File

@@ -11,16 +11,13 @@
width: 794px;
height: 1123px;
}
.bigTitle{
font-size: 60px;
margin: 0;
line-height: 1;
margin-bottom: 25px;
font-weight: 500;
color: #333;
}
.details {
display: flex;
flex-direction: column;
@@ -35,13 +32,11 @@
min-width: 120px;
color: #333;
}
.addressRoot{
> div{
flex: 1;
}
}
.table {
width: 100%;
border-collapse: collapse;
@@ -66,10 +61,6 @@
}
tbody{
tr {
}
td{
border-bottom: 1px solid #F6F6F6;
padding: 12px 10px;
@@ -80,7 +71,6 @@
&:last-of-type{
padding-right: 0;
}
&.rate,
&.total{
text-align: right;
@@ -88,7 +78,6 @@
}
}
}
.totals{
display: flex;
flex-direction: column;
@@ -112,25 +101,22 @@
.totalBottomGrayBordered {
border-bottom: 1px solid #DADADA;
}
.logoWrap{
height: 120px;
width: 120px;
position: absolute;
right: 26px;
top: 26px;
border-radius: 5px;
overflow: hidden;
img{
max-width: 100%;
}
}
.logoImg {
height: auto;
width: auto;
max-width: 400px;
max-height: 160px;
}
.footer{
}
.paragraph{
margin-bottom: 20px;
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { PaperTemplate, PaperTemplateTotalBorder } from './PaperTemplate';
import { Box, Stack } from '@/components';
import { Box, Group, Stack } from '@/components';
import {
DefaultPdfTemplateTerms,
DefaultPdfTemplateItemDescription,
@@ -178,31 +178,35 @@ export function InvoicePaperTemplate({
statement = DefaultPdfTemplateStatement,
}: InvoicePaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogoUri={companyLogoUri}
bigtitle={'Invoice'}
>
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showInvoiceNumber && (
<PaperTemplate.TermsItem label={invoiceNumberLabel}>
{invoiceNumber}
</PaperTemplate.TermsItem>
<Group align="start" spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Invoice'} />
<PaperTemplate.TermsList>
{showInvoiceNumber && (
<PaperTemplate.TermsItem label={invoiceNumberLabel}>
{invoiceNumber}
</PaperTemplate.TermsItem>
)}
{showDateIssue && (
<PaperTemplate.TermsItem label={dateIssueLabel}>
{dateIssue}
</PaperTemplate.TermsItem>
)}
{showDueDate && (
<PaperTemplate.TermsItem label={dueDateLabel}>
{dueDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Stack>
{companyLogoUri && showCompanyLogo && (
<PaperTemplate.Logo logoUri={companyLogoUri} />
)}
{showDateIssue && (
<PaperTemplate.TermsItem label={dateIssueLabel}>
{dateIssue}
</PaperTemplate.TermsItem>
)}
{showDueDate && (
<PaperTemplate.TermsItem label={dueDateLabel}>
{dueDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (

View File

@@ -7,38 +7,18 @@ import styles from './InvoicePaperTemplate.module.scss';
export interface PaperTemplateProps {
primaryColor?: string;
secondaryColor?: string;
showCompanyLogo?: boolean;
companyLogoUri?: string;
companyName?: string;
bigtitle?: string;
children?: React.ReactNode;
}
export function PaperTemplate({
primaryColor,
secondaryColor,
showCompanyLogo,
companyLogoUri,
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 && companyLogoUri && (
<div className={styles.logoWrap}>
<img alt="" src={companyLogoUri} />
</div>
)}
</div>
{children}
</div>
);
@@ -53,6 +33,26 @@ interface PaperTemplateTableProps {
data: Array<Record<string, any>>;
}
interface PaperTemplateBigTitleProps {
title: string;
}
PaperTemplate.BigTitle = ({ title }: PaperTemplateBigTitleProps) => {
return <h1 className={styles.bigTitle}>{title}</h1>;
};
interface PaperTemplateLogoProps {
logoUri: string;
}
PaperTemplate.Logo = ({ logoUri }: PaperTemplateLogoProps) => {
return (
<div className={styles.logoWrap}>
<img className={styles.logoImg} alt="" src={logoUri} />
</div>
);
};
PaperTemplate.Table = ({ columns, data }: PaperTemplateTableProps) => {
return (
<table className={styles.table}>

View File

@@ -1,4 +1,4 @@
import { Box, Stack } from '@/components';
import { Box, Group, Stack } from '@/components';
import {
PaperTemplate,
PaperTemplateProps,
@@ -10,6 +10,13 @@ import {
} from '@/constants/PdfTemplates';
export interface PaymentReceivedPaperTemplateProps extends PaperTemplateProps {
// # Company logo
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Company name
companyName?: string;
// Customer address
showCustomerAddress?: boolean;
customerAddress?: string;
@@ -93,27 +100,31 @@ export function PaymentReceivedPaperTemplate({
paymentReceivedDateLabel = 'Payment Date',
}: PaymentReceivedPaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogoUri={companyLogoUri}
bigtitle={'Payment'}
>
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showPaymentReceivedNumber && (
<PaperTemplate.TermsItem label={paymentReceivedNumberLabel}>
{paymentReceivedNumebr}
</PaperTemplate.TermsItem>
)}
<Group align={'start'} spacing={10}>
<Stack flex={1}>
<PaperTemplate.BigTitle title={'Payment'} />
{showPaymentReceivedDate && (
<PaperTemplate.TermsItem label={paymentReceivedDateLabel}>
{paymentReceivedDate}
</PaperTemplate.TermsItem>
<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} />
)}
</PaperTemplate.TermsList>
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (

View File

@@ -1,4 +1,4 @@
import { Box, Stack } from '@/components';
import { Box, Group, Stack } from '@/components';
import {
PaperTemplate,
PaperTemplateProps,
@@ -13,6 +13,13 @@ import {
} from '@/constants/PdfTemplates';
export interface ReceiptPaperTemplateProps extends PaperTemplateProps {
// # Company logo
showCompanyLogo?: boolean;
companyLogoUri?: string;
// # Company name
companyName?: string;
// Addresses
showCustomerAddress?: boolean;
customerAddress?: string;
@@ -117,26 +124,30 @@ export function ReceiptPaperTemplate({
receiptDateLabel = 'Receipt Date',
}: ReceiptPaperTemplateProps) {
return (
<PaperTemplate
primaryColor={primaryColor}
secondaryColor={secondaryColor}
showCompanyLogo={showCompanyLogo}
companyLogoUri={companyLogoUri}
bigtitle={'Receipt'}
>
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
<Stack spacing={24}>
<PaperTemplate.TermsList>
{showReceiptNumber && (
<PaperTemplate.TermsItem label={receiptNumberLabel}>
{receiptNumebr}
</PaperTemplate.TermsItem>
<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} />
)}
{showReceiptDate && (
<PaperTemplate.TermsItem label={receiptDateLabel}>
{receiptDate}
</PaperTemplate.TermsItem>
)}
</PaperTemplate.TermsList>
</Group>
<PaperTemplate.AddressesGroup>
{showCompanyAddress && (