mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
feat: email templates
This commit is contained in:
@@ -18,4 +18,16 @@ export const Default: StoryFn<CreditNoteEmailProps> = Template.bind({});
|
|||||||
Default.args = {
|
Default.args = {
|
||||||
total: '$1,000.00',
|
total: '$1,000.00',
|
||||||
items: [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
|
items: [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
|
||||||
|
message: `Hi Ahmed Bouhuolia,
|
||||||
|
|
||||||
|
Here's invoice # INV-00005 for $1,000.00
|
||||||
|
|
||||||
|
The amount outstanding of $1,000.00 is due on 10 Oct 2024.
|
||||||
|
|
||||||
|
From your online payment page you can print a PDF or view your outstanding bills.
|
||||||
|
|
||||||
|
If you have any questions, please let us know.
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
Bigcapital`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,43 @@
|
|||||||
export interface CreditNoteEmailProps {
|
import {
|
||||||
preview?: string;
|
Button,
|
||||||
|
Column,
|
||||||
|
Container,
|
||||||
|
Heading,
|
||||||
|
Row,
|
||||||
|
Section,
|
||||||
|
Text,
|
||||||
|
} from '@react-email/components';
|
||||||
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
import { EmailTemplate } from './EmailTemplate';
|
||||||
|
|
||||||
|
export interface CreditNoteEmailProps {
|
||||||
|
preview: string;
|
||||||
|
|
||||||
|
// # Company
|
||||||
companyName?: string;
|
companyName?: string;
|
||||||
companyLogoUri: string;
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
// # Color
|
||||||
primaryColor?: string;
|
primaryColor?: string;
|
||||||
|
|
||||||
|
// # Total
|
||||||
total: string;
|
total: string;
|
||||||
totalLabel?: string;
|
totalLabel?: string;
|
||||||
|
|
||||||
// # Items
|
// # Items
|
||||||
items: Array<{ label: string; quantity: string; rate: string }>;
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
viewEstimateButtonLabel?: string;
|
// # View button
|
||||||
viewEstimateButtonUrl?: string;
|
viewButtonLabel?: string;
|
||||||
|
viewButtonUrl?: string;
|
||||||
|
|
||||||
|
// # Credit Note #
|
||||||
|
creditNoteNumber?: string;
|
||||||
|
creditNoteNumberLabel?: string;
|
||||||
|
|
||||||
|
// # Message
|
||||||
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CreditNoteEmailTemplate: React.FC<
|
export const CreditNoteEmailTemplate: React.FC<
|
||||||
@@ -22,19 +46,179 @@ export const CreditNoteEmailTemplate: React.FC<
|
|||||||
preview,
|
preview,
|
||||||
|
|
||||||
// # Company
|
// # Company
|
||||||
companyName,
|
companyName = 'Bigcapital, Inc.',
|
||||||
companyLogoUri,
|
companyLogoUri,
|
||||||
|
|
||||||
// # Colors
|
// # Colors
|
||||||
primaryColor = 'rgb(0, 82, 204)',
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
// # invoice total
|
// # Invoice total
|
||||||
total,
|
total,
|
||||||
totalLabel = 'Total',
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # Credit Note #
|
||||||
|
creditNoteNumberLabel = 'Credit Note # {creditNoteNumber}',
|
||||||
|
creditNoteNumber = 'CN-00001',
|
||||||
|
|
||||||
// # View invoice button
|
// # View invoice button
|
||||||
viewEstimateButtonLabel = 'View Estimate',
|
viewButtonLabel = 'View Credit Note',
|
||||||
viewEstimateButtonUrl,
|
viewButtonUrl,
|
||||||
|
|
||||||
|
// # Message
|
||||||
|
message = '',
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items = [],
|
||||||
}) => {
|
}) => {
|
||||||
return <h1>asdasd</h1>;
|
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>
|
||||||
|
</EmailTemplate>
|
||||||
|
</EmailTemplateLayout>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const containerStyle: CSSProperties = {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: '500px',
|
||||||
|
padding: '35px 25px',
|
||||||
|
color: '#000',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerInfoStyle: CSSProperties = {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mainSectionStyle: CSSProperties = {};
|
||||||
|
|
||||||
|
const invoiceAmountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
color: '#383E47',
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const creditNumberStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '13px',
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const companyNameStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '18px',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewInvoiceButtonStyle: CSSProperties = {
|
||||||
|
display: 'block',
|
||||||
|
cursor: 'pointer',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 16,
|
||||||
|
padding: '10px 15px',
|
||||||
|
lineHeight: '1',
|
||||||
|
backgroundColor: 'rgb(0, 82, 204)',
|
||||||
|
color: '#fff',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItemLabelStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItemAmountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
textAlign: 'right',
|
||||||
|
};
|
||||||
|
|
||||||
|
const messageStyle: CSSProperties = {
|
||||||
|
whiteSpace: 'pre-line',
|
||||||
|
color: '#252A31',
|
||||||
|
margin: '0 0 20px 0',
|
||||||
|
lineHeight: '20px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineRowStyle: CSSProperties = {
|
||||||
|
borderBottom: '1px solid #000',
|
||||||
|
height: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineItemLabelStyle: CSSProperties = {
|
||||||
|
...listItemLabelStyle,
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineItemAmountStyle: CSSProperties = {
|
||||||
|
...listItemAmountStyle,
|
||||||
|
fontWeight: 600,
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemLineRowStyle: CSSProperties = {
|
||||||
|
borderBottom: '1px solid #D9D9D9',
|
||||||
|
height: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalsSectionStyle = {
|
||||||
|
marginTop: '20px',
|
||||||
|
borderTop: '1px solid #D9D9D9',
|
||||||
|
};
|
||||||
|
|||||||
48
shared/email-components/src/lib/EmailTemplate.tsx
Normal file
48
shared/email-components/src/lib/EmailTemplate.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { Container, Section } from '@react-email/components';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
|
||||||
|
interface EmailTemplateProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
export function EmailTemplate({ children }: EmailTemplateProps) {
|
||||||
|
return <Container style={containerStyle}>{children}</Container>;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailTemplate.CompanyLogo = ({ src }: { src: string }) => {
|
||||||
|
return (
|
||||||
|
<Section style={logoSectionStyle}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...companyLogoStyle,
|
||||||
|
backgroundImage: `url("${src}")`,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const containerStyle: CSSProperties = {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: '500px',
|
||||||
|
padding: '35px 25px',
|
||||||
|
color: '#000',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const companyLogoStyle = {
|
||||||
|
height: 90,
|
||||||
|
width: 90,
|
||||||
|
borderRadius: '3px',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
textIndent: '-999999px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center center',
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
};
|
||||||
|
|
||||||
|
const logoSectionStyle = {
|
||||||
|
marginBottom: '15px',
|
||||||
|
};
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from '@react-email/components';
|
} from '@react-email/components';
|
||||||
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
import { EmailTemplate } from './EmailTemplate';
|
||||||
|
|
||||||
export interface EstimatePaymentEmailProps {
|
export interface EstimatePaymentEmailProps {
|
||||||
preview: string;
|
preview: string;
|
||||||
@@ -79,17 +80,8 @@ export const EstimatePaymentEmail: React.FC<
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<EmailTemplateLayout preview={preview}>
|
<EmailTemplateLayout preview={preview}>
|
||||||
<Container style={containerStyle}>
|
<EmailTemplate>
|
||||||
{companyLogoUri && (
|
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
|
||||||
<Section style={logoSectionStyle}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
...companyLogoStyle,
|
|
||||||
backgroundImage: `url("${companyLogoUri}")`,
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</Section>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Section style={headerInfoStyle}>
|
<Section style={headerInfoStyle}>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -146,21 +138,11 @@ export const EstimatePaymentEmail: React.FC<
|
|||||||
</Column>
|
</Column>
|
||||||
</Row>
|
</Row>
|
||||||
</Section>
|
</Section>
|
||||||
|
</EmailTemplate>
|
||||||
</Container>
|
|
||||||
</EmailTemplateLayout>
|
</EmailTemplateLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const containerStyle: CSSProperties = {
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: '500px',
|
|
||||||
padding: '35px 25px',
|
|
||||||
color: '#000',
|
|
||||||
borderRadius: '5px',
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerInfoStyle: CSSProperties = {
|
const headerInfoStyle: CSSProperties = {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
@@ -240,20 +222,3 @@ const totalsSectionStyle = {
|
|||||||
marginTop: '20px',
|
marginTop: '20px',
|
||||||
borderTop: '1px solid #D9D9D9',
|
borderTop: '1px solid #D9D9D9',
|
||||||
};
|
};
|
||||||
|
|
||||||
const logoSectionStyle = {
|
|
||||||
marginBottom: '15px',
|
|
||||||
};
|
|
||||||
|
|
||||||
const companyLogoStyle = {
|
|
||||||
height: 90,
|
|
||||||
width: 90,
|
|
||||||
borderRadius: '3px',
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
textIndent: '-999999px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundPosition: 'center center',
|
|
||||||
backgroundSize: 'contain',
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
Html,
|
|
||||||
Button,
|
Button,
|
||||||
Head,
|
|
||||||
Body,
|
|
||||||
Container,
|
Container,
|
||||||
Section,
|
Section,
|
||||||
Heading,
|
Heading,
|
||||||
Text,
|
Text,
|
||||||
Preview,
|
|
||||||
Tailwind,
|
|
||||||
Row,
|
Row,
|
||||||
Column,
|
Column,
|
||||||
render,
|
render,
|
||||||
} from '@react-email/components';
|
} from '@react-email/components';
|
||||||
import { CSSProperties } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
import { EmailTemplate } from './EmailTemplate';
|
||||||
|
|
||||||
export interface InvoicePaymentEmailProps {
|
export interface InvoicePaymentEmailProps {
|
||||||
preview: string;
|
preview: string;
|
||||||
@@ -98,18 +94,9 @@ export const InvoicePaymentEmail: React.FC<
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<EmailTemplateLayout preview={preview}>
|
<EmailTemplateLayout preview={preview}>
|
||||||
<Container style={containerStyle}>
|
<EmailTemplate>
|
||||||
<Section style={mainSectionStyle}>
|
<Section style={mainSectionStyle}>
|
||||||
{companyLogoUri && (
|
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
|
||||||
<Section style={logoSectionStyle}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
...companyLogoStyle,
|
|
||||||
backgroundImage: `url("${companyLogoUri}")`,
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</Section>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Section style={headerInfoStyle}>
|
<Section style={headerInfoStyle}>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -179,7 +166,7 @@ export const InvoicePaymentEmail: React.FC<
|
|||||||
</Row>
|
</Row>
|
||||||
</Section>
|
</Section>
|
||||||
</Section>
|
</Section>
|
||||||
</Container>
|
</EmailTemplate>
|
||||||
</EmailTemplateLayout>
|
</EmailTemplateLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -293,20 +280,3 @@ const totalsSectionStyle = {
|
|||||||
marginTop: '20px',
|
marginTop: '20px',
|
||||||
borderTop: '1px solid #D9D9D9',
|
borderTop: '1px solid #D9D9D9',
|
||||||
};
|
};
|
||||||
|
|
||||||
const logoSectionStyle = {
|
|
||||||
marginBottom: '15px',
|
|
||||||
};
|
|
||||||
|
|
||||||
const companyLogoStyle = {
|
|
||||||
height: 90,
|
|
||||||
width: 90,
|
|
||||||
borderRadius: '3px',
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
textIndent: '-999999px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundPosition: 'center center',
|
|
||||||
backgroundSize: 'contain',
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -14,6 +14,19 @@ const Template: StoryFn<PaymentReceivedEmailTemplateProps> = (args) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const Default: StoryFn<PaymentReceivedEmailTemplateProps> =
|
export const Default: StoryFn<PaymentReceivedEmailTemplateProps> =
|
||||||
Template.bind({});
|
Template.bind({
|
||||||
|
message: `Hi Ahmed Bouhuolia,
|
||||||
|
|
||||||
|
Here's invoice # INV-00005 for $1,000.00
|
||||||
|
|
||||||
|
The amount outstanding of $1,000.00 is due on 10 Oct 2024.
|
||||||
|
|
||||||
|
From your online payment page you can print a PDF or view your outstanding bills.
|
||||||
|
|
||||||
|
If you have any questions, please let us know.
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
Bigcapital`,
|
||||||
|
});
|
||||||
|
|
||||||
Default.args = {};
|
Default.args = {};
|
||||||
|
|||||||
@@ -1,19 +1,39 @@
|
|||||||
export interface PaymentReceivedEmailTemplateProps {
|
import {
|
||||||
preview?: string;
|
Button,
|
||||||
|
Container,
|
||||||
|
Heading,
|
||||||
|
Row,
|
||||||
|
Section,
|
||||||
|
Text,
|
||||||
|
} from '@react-email/components';
|
||||||
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
|
||||||
|
export interface PaymentReceivedEmailTemplateProps {
|
||||||
|
preview: string;
|
||||||
|
|
||||||
|
// # Company
|
||||||
companyName?: string;
|
companyName?: string;
|
||||||
companyLogoUri: string;
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
// # Color
|
||||||
primaryColor?: string;
|
primaryColor?: string;
|
||||||
|
|
||||||
|
// # Total
|
||||||
total: string;
|
total: string;
|
||||||
totalLabel?: string;
|
totalLabel?: string;
|
||||||
|
|
||||||
// # Items
|
// # Items
|
||||||
items: Array<{ label: string; quantity: string; rate: string }>;
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
viewEstimateButtonLabel?: string;
|
// # View payment button
|
||||||
viewEstimateButtonUrl?: string;
|
viewPaymentButtonLabel?: string;
|
||||||
|
viewPaymentButtonUrl?: string;
|
||||||
|
|
||||||
|
paymentNumberLabel?: string;
|
||||||
|
paymentNumber?: string;
|
||||||
|
|
||||||
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PaymentReceivedEmailTemplate: React.FC<
|
export const PaymentReceivedEmailTemplate: React.FC<
|
||||||
@@ -22,19 +42,136 @@ export const PaymentReceivedEmailTemplate: React.FC<
|
|||||||
preview,
|
preview,
|
||||||
|
|
||||||
// # Company
|
// # Company
|
||||||
companyName,
|
companyName = 'Bigcapital, Inc.',
|
||||||
companyLogoUri,
|
companyLogoUri,
|
||||||
|
|
||||||
// # Colors
|
// # Colors
|
||||||
primaryColor = 'rgb(0, 82, 204)',
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
// # invoice total
|
// # Payment #
|
||||||
total,
|
paymentNumberLabel = 'Payment # {paymentNumber}',
|
||||||
|
paymentNumber = 'PAY-00001',
|
||||||
|
|
||||||
|
// # Total
|
||||||
|
total = '$1,000.00',
|
||||||
totalLabel = 'Total',
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items,
|
||||||
|
|
||||||
|
message = '',
|
||||||
|
|
||||||
// # View invoice button
|
// # View invoice button
|
||||||
viewEstimateButtonLabel = 'View Estimate',
|
viewPaymentButtonLabel = 'View Payment',
|
||||||
viewEstimateButtonUrl,
|
viewPaymentButtonUrl,
|
||||||
}) => {
|
}) => {
|
||||||
return <h1>asdasd</h1>;
|
return (
|
||||||
|
<EmailTemplateLayout preview={preview}>
|
||||||
|
<Container style={containerStyle}>
|
||||||
|
{companyLogoUri && (
|
||||||
|
<Section style={logoSectionStyle}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...companyLogoStyle,
|
||||||
|
backgroundImage: `url("${companyLogoUri}")`,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
|
<Section style={headerInfoStyle}>
|
||||||
|
<Row>
|
||||||
|
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text style={paymentAmountStyle}>{total}</Text>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text style={paymentNumberStyle}>
|
||||||
|
{paymentNumberLabel?.replace('{paymentNumber}', paymentNumber)}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Text style={invoiceMessageStyle}>{message}</Text>
|
||||||
|
<Button
|
||||||
|
href={viewPaymentButtonUrl}
|
||||||
|
style={{
|
||||||
|
...viewInvoiceButtonStyle,
|
||||||
|
backgroundColor: primaryColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{viewPaymentButtonLabel}
|
||||||
|
</Button>
|
||||||
|
</Container>
|
||||||
|
</EmailTemplateLayout>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const containerStyle: CSSProperties = {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: '500px',
|
||||||
|
padding: '35px 25px',
|
||||||
|
color: '#000',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerInfoStyle: CSSProperties = {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 20,
|
||||||
|
};
|
||||||
|
const mainSectionStyle: CSSProperties = {};
|
||||||
|
|
||||||
|
const paymentAmountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
color: '#383E47',
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
const paymentNumberStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '13px',
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceCompanyNameStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '18px',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewInvoiceButtonStyle: CSSProperties = {
|
||||||
|
display: 'block',
|
||||||
|
cursor: 'pointer',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 16,
|
||||||
|
padding: '10px 15px',
|
||||||
|
lineHeight: '1',
|
||||||
|
backgroundColor: 'rgb(0, 82, 204)',
|
||||||
|
color: '#fff',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceMessageStyle: CSSProperties = {
|
||||||
|
whiteSpace: 'pre-line',
|
||||||
|
color: '#252A31',
|
||||||
|
margin: '0 0 20px 0',
|
||||||
|
lineHeight: '20px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const logoSectionStyle = {
|
||||||
|
marginBottom: '15px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const companyLogoStyle = {
|
||||||
|
height: 90,
|
||||||
|
width: 90,
|
||||||
|
borderRadius: '3px',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
textIndent: '-999999px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center center',
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
};
|
||||||
|
|||||||
@@ -16,5 +16,16 @@ const Template: StoryFn<ReceiptEmailTemplateProps> = (args) => (
|
|||||||
export const Default: StoryFn<ReceiptEmailTemplateProps> = Template.bind({});
|
export const Default: StoryFn<ReceiptEmailTemplateProps> = Template.bind({});
|
||||||
|
|
||||||
Default.args = {
|
Default.args = {
|
||||||
// Add default props here
|
message: `Hi Ahmed Bouhuolia,
|
||||||
|
|
||||||
|
Here's invoice # INV-00005 for $1,000.00
|
||||||
|
|
||||||
|
The amount outstanding of $1,000.00 is due on 10 Oct 2024.
|
||||||
|
|
||||||
|
From your online payment page you can print a PDF or view your outstanding bills.
|
||||||
|
|
||||||
|
If you have any questions, please let us know.
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
Bigcapital`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Column,
|
||||||
|
Container,
|
||||||
|
Heading,
|
||||||
|
Row,
|
||||||
|
Section,
|
||||||
|
Text,
|
||||||
|
} from '@react-email/components';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
import { EmailTemplate } from './EmailTemplate';
|
||||||
|
|
||||||
export interface ReceiptEmailTemplateProps {
|
export interface ReceiptEmailTemplateProps {
|
||||||
preview?: string;
|
preview: string;
|
||||||
|
|
||||||
// # Company
|
// # Company
|
||||||
companyName?: string;
|
companyName?: string;
|
||||||
@@ -12,11 +25,23 @@ export interface ReceiptEmailTemplateProps {
|
|||||||
total: string;
|
total: string;
|
||||||
totalLabel?: string;
|
totalLabel?: string;
|
||||||
|
|
||||||
|
// # Receipt #
|
||||||
|
receiptNumber?: string;
|
||||||
|
receiptNumberLabel?: string;
|
||||||
|
|
||||||
// # Items
|
// # Items
|
||||||
items: Array<{ label: string; quantity: string; rate: string }>;
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
|
// # Subtotal
|
||||||
|
subtotal?: string;
|
||||||
|
subtotalLabel?: string;
|
||||||
|
|
||||||
|
// # View receipt button.
|
||||||
viewReceiptButtonLabel?: string;
|
viewReceiptButtonLabel?: string;
|
||||||
viewReceiptButtonUrl?: string;
|
viewReceiptButtonUrl?: string;
|
||||||
|
|
||||||
|
// # Message
|
||||||
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReceiptEmailTemplate: React.FC<
|
export const ReceiptEmailTemplate: React.FC<
|
||||||
@@ -25,21 +50,186 @@ export const ReceiptEmailTemplate: React.FC<
|
|||||||
preview,
|
preview,
|
||||||
|
|
||||||
// # Company
|
// # Company
|
||||||
companyName,
|
companyName = 'Bigcapital, Inc.',
|
||||||
companyLogoUri,
|
companyLogoUri,
|
||||||
|
|
||||||
// # Colors
|
// # Colors
|
||||||
primaryColor = 'rgb(0, 82, 204)',
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
// # Invoice total
|
// # Invoice total
|
||||||
total,
|
total = '$1,000.00',
|
||||||
totalLabel = 'Total',
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # Subtotal
|
||||||
|
subtotal = '$1,000.00',
|
||||||
|
subtotalLabel = 'Subtotal',
|
||||||
|
|
||||||
|
// # Receipt #
|
||||||
|
receiptNumberLabel = 'Receipt # {receiptNumber}',
|
||||||
|
receiptNumber = 'REC-00001',
|
||||||
|
|
||||||
// # View invoice button
|
// # View invoice button
|
||||||
viewReceiptButtonLabel = 'View Estimate',
|
viewReceiptButtonLabel = 'View Estimate',
|
||||||
viewReceiptButtonUrl,
|
viewReceiptButtonUrl,
|
||||||
|
|
||||||
|
// # Message
|
||||||
|
message = '',
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items = [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<h1>asdasd</h1>
|
<EmailTemplateLayout preview={preview}>
|
||||||
)
|
<EmailTemplate>
|
||||||
|
{companyLogoUri && <EmailTemplate.CompanyLogo src={companyLogoUri} />}
|
||||||
|
|
||||||
|
<Section style={headerInfoStyle}>
|
||||||
|
<Row>
|
||||||
|
<Heading style={invoiceCompanyNameStyle}>{companyName}</Heading>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text style={amountStyle}>{total}</Text>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Text style={receiptNumberStyle}>
|
||||||
|
{receiptNumberLabel?.replace('{receiptNumber}', receiptNumber)}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Text style={messageStyle}>{message}</Text>
|
||||||
|
<Button
|
||||||
|
href={viewReceiptButtonUrl}
|
||||||
|
style={{
|
||||||
|
...viewInvoiceButtonStyle,
|
||||||
|
backgroundColor: primaryColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{viewReceiptButtonLabel}
|
||||||
|
</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={dueAmountLineItemLabelStyle}>{subtotalLabel}</Text>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column width={'50%'}>
|
||||||
|
<Text style={dueAmountLineItemAmountStyle}>{subtotal}</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>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const headerInfoStyle: CSSProperties = {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
const amountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
color: '#383E47',
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
const receiptNumberStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '13px',
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceCompanyNameStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '18px',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewInvoiceButtonStyle: CSSProperties = {
|
||||||
|
display: 'block',
|
||||||
|
cursor: 'pointer',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 16,
|
||||||
|
padding: '10px 15px',
|
||||||
|
lineHeight: '1',
|
||||||
|
backgroundColor: 'rgb(0, 82, 204)',
|
||||||
|
color: '#fff',
|
||||||
|
borderRadius: '5px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItemLabelStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const listItemAmountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
textAlign: 'right',
|
||||||
|
};
|
||||||
|
|
||||||
|
const messageStyle: CSSProperties = {
|
||||||
|
whiteSpace: 'pre-line',
|
||||||
|
color: '#000000',
|
||||||
|
margin: '0 0 20px 0',
|
||||||
|
lineHeight: '20px',
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineRowStyle: CSSProperties = {
|
||||||
|
borderBottom: '1px solid #000',
|
||||||
|
height: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineItemLabelStyle: CSSProperties = {
|
||||||
|
...listItemLabelStyle,
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalLineItemAmountStyle: CSSProperties = {
|
||||||
|
...listItemAmountStyle,
|
||||||
|
fontWeight: 600,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dueAmountLineItemLabelStyle: CSSProperties = {
|
||||||
|
...listItemLabelStyle,
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dueAmountLineItemAmountStyle: CSSProperties = {
|
||||||
|
...listItemAmountStyle,
|
||||||
|
fontWeight: 600,
|
||||||
|
};
|
||||||
|
|
||||||
|
const itemLineRowStyle: CSSProperties = {
|
||||||
|
borderBottom: '1px solid #D9D9D9',
|
||||||
|
height: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalsSectionStyle = {
|
||||||
|
marginTop: '20px',
|
||||||
|
borderTop: '1px solid #D9D9D9',
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user