mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 07:10:33 +00:00
feat: wip email templates
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
import { FCheckbox, FFormGroup, FInputGroup, Group, Stack } from "@/components";
|
import { useFormikContext } from 'formik';
|
||||||
import { SendMailViewToAddressField } from "../SendMailViewDrawer/SendMailViewToAddressField";
|
import { FCheckbox, FFormGroup, FInputGroup, Group, Stack } from '@/components';
|
||||||
import { SendMailViewMessageField } from "../SendMailViewDrawer/SendMailViewMessageField";
|
import { SendMailViewToAddressField } from '../SendMailViewDrawer/SendMailViewToAddressField';
|
||||||
import { Button, Intent } from "@blueprintjs/core";
|
import { SendMailViewMessageField } from '../SendMailViewDrawer/SendMailViewMessageField';
|
||||||
import { useFormikContext } from "formik";
|
import { Button, Intent } from '@blueprintjs/core';
|
||||||
import { useDrawerContext } from "@/components/Drawer/DrawerProvider";
|
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||||
import { useDrawerActions } from "@/hooks/state";
|
import { useDrawerActions } from '@/hooks/state';
|
||||||
|
|
||||||
const items: Array<any> = [];
|
const items: Array<any> = [];
|
||||||
const argsOptions: Array<any> = [];
|
const argsOptions: Array<any> = [];
|
||||||
@@ -34,7 +34,6 @@ export function EstimateSendMailFields() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function EstimateSendMailFooter() {
|
function EstimateSendMailFooter() {
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
const { name } = useDrawerContext();
|
const { name } = useDrawerContext();
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { Meta, StoryFn } from '@storybook/react';
|
||||||
|
import {
|
||||||
|
CreditNoteEmailProps,
|
||||||
|
CreditNoteEmailTemplate,
|
||||||
|
} from './CreditNoteEmailTemplate';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Email/CreditNoteEmailTemplate',
|
||||||
|
component: CreditNoteEmailTemplate,
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: StoryFn<CreditNoteEmailProps> = (args) => (
|
||||||
|
<CreditNoteEmailTemplate {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Default: StoryFn<CreditNoteEmailProps> = Template.bind({});
|
||||||
|
|
||||||
|
Default.args = {
|
||||||
|
total: '$1,000.00',
|
||||||
|
items: [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
|
||||||
|
};
|
||||||
40
shared/email-components/src/lib/CreditNoteEmailTemplate.tsx
Normal file
40
shared/email-components/src/lib/CreditNoteEmailTemplate.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
export interface CreditNoteEmailProps {
|
||||||
|
preview?: string;
|
||||||
|
|
||||||
|
companyName?: string;
|
||||||
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
primaryColor?: string;
|
||||||
|
|
||||||
|
total: string;
|
||||||
|
totalLabel?: string;
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
|
viewEstimateButtonLabel?: string;
|
||||||
|
viewEstimateButtonUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CreditNoteEmailTemplate: React.FC<
|
||||||
|
Readonly<CreditNoteEmailProps>
|
||||||
|
> = ({
|
||||||
|
preview,
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName,
|
||||||
|
companyLogoUri,
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
|
// # invoice total
|
||||||
|
total,
|
||||||
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # View invoice button
|
||||||
|
viewEstimateButtonLabel = 'View Estimate',
|
||||||
|
viewEstimateButtonUrl,
|
||||||
|
}) => {
|
||||||
|
return <h1>asdasd</h1>;
|
||||||
|
};
|
||||||
29
shared/email-components/src/lib/EmailTemplateLayout.tsx
Normal file
29
shared/email-components/src/lib/EmailTemplateLayout.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Html, Head, Body, Preview, Tailwind } from '@react-email/components';
|
||||||
|
import { CSSProperties } from 'react';
|
||||||
|
|
||||||
|
interface EmailTemplateLayoutProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
preview: string;
|
||||||
|
}
|
||||||
|
export const EmailTemplateLayout = ({
|
||||||
|
children,
|
||||||
|
preview,
|
||||||
|
}: EmailTemplateLayoutProps) => {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<Preview>{preview}</Preview>
|
||||||
|
|
||||||
|
<Tailwind>
|
||||||
|
<Body style={bodyStyle}>{children}</Body>
|
||||||
|
</Tailwind>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bodyStyle: CSSProperties = {
|
||||||
|
backgroundColor: '#F5F5F5',
|
||||||
|
fontFamily:
|
||||||
|
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
|
||||||
|
padding: '40px 0',
|
||||||
|
};
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Meta, StoryFn } from '@storybook/react';
|
||||||
|
import {
|
||||||
|
EstimatePaymentEmailProps,
|
||||||
|
EstimatePaymentEmail,
|
||||||
|
} from './EstimatePaymentEmail';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Email/EstimatePaymentEmail',
|
||||||
|
component: EstimatePaymentEmail,
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: StoryFn<EstimatePaymentEmailProps> = (args) => (
|
||||||
|
<EstimatePaymentEmail {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Default: StoryFn<EstimatePaymentEmailProps> = Template.bind({});
|
||||||
|
|
||||||
|
Default.args = {
|
||||||
|
total: '$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`,
|
||||||
|
};
|
||||||
259
shared/email-components/src/lib/EstimatePaymentEmail.tsx
Normal file
259
shared/email-components/src/lib/EstimatePaymentEmail.tsx
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
import { CSSProperties } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Column,
|
||||||
|
Container,
|
||||||
|
Heading,
|
||||||
|
Row,
|
||||||
|
Section,
|
||||||
|
Text,
|
||||||
|
} from '@react-email/components';
|
||||||
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
|
||||||
|
export interface EstimatePaymentEmailProps {
|
||||||
|
preview: string;
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName?: string;
|
||||||
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor?: string;
|
||||||
|
|
||||||
|
// # Total
|
||||||
|
total: string;
|
||||||
|
totalLabel?: string;
|
||||||
|
|
||||||
|
// # Estimate No#
|
||||||
|
estimateNumber?: string;
|
||||||
|
estimateNumberLabel?: string;
|
||||||
|
|
||||||
|
// # Expiration date.
|
||||||
|
expirationDateLabel?: string;
|
||||||
|
expirationDate?: string;
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
|
// # View estimate button.
|
||||||
|
viewEstimateButtonLabel?: string;
|
||||||
|
viewEstimateButtonUrl?: string;
|
||||||
|
|
||||||
|
// # Estimate message
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EstimatePaymentEmail: React.FC<
|
||||||
|
Readonly<EstimatePaymentEmailProps>
|
||||||
|
> = ({
|
||||||
|
preview,
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName,
|
||||||
|
companyLogoUri,
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
|
// # invoice total
|
||||||
|
total,
|
||||||
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # Estimate No#
|
||||||
|
estimateNumberLabel = 'Estimate No: {estimateNumber}',
|
||||||
|
estimateNumber = 'EST-00001',
|
||||||
|
|
||||||
|
// # Expiration date
|
||||||
|
expirationDateLabel = 'Expiration Date: {expirationDate}',
|
||||||
|
expirationDate = '12/12/2021',
|
||||||
|
|
||||||
|
// # View invoice button
|
||||||
|
viewEstimateButtonLabel = 'View Estimate',
|
||||||
|
viewEstimateButtonUrl,
|
||||||
|
|
||||||
|
// # Message
|
||||||
|
message = '',
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items = [],
|
||||||
|
}) => {
|
||||||
|
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={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 style={totalLineRowStyle}>
|
||||||
|
<Column width={'50%'}>
|
||||||
|
<Text style={totalLineItemLabelStyle}>{totalLabel}</Text>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column width={'50%'}>
|
||||||
|
<Text style={totalLineItemAmountStyle}>{total}</Text>
|
||||||
|
</Column>
|
||||||
|
</Row>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
</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 estimateAmountStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
color: '#383E47',
|
||||||
|
fontWeight: 500,
|
||||||
|
};
|
||||||
|
const estimateNumberStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '13px',
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
const estimateExpirationStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '13px',
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceCompanyNameStyle: CSSProperties = {
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '18px',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: '#404854',
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewEstimateButtonStyle: 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 estimateMessageStyle: 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',
|
||||||
|
};
|
||||||
|
|
||||||
|
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,18 +1,38 @@
|
|||||||
|
import { Meta, StoryFn } from '@storybook/react';
|
||||||
import { Meta } from '@storybook/react';
|
|
||||||
import { StoryFn } from '@storybook/react';
|
|
||||||
import {
|
import {
|
||||||
InvoicePaymentEmail,
|
InvoicePaymentEmail,
|
||||||
InvoicePaymentEmailProps,
|
InvoicePaymentEmailProps,
|
||||||
} from './InvoicePaymentEmail';
|
} from './InvoicePaymentEmail';
|
||||||
|
|
||||||
const meta: Meta<typeof InvoicePaymentEmail> = {
|
export default {
|
||||||
title: 'Invoice Payment Email',
|
title: 'Email/InvoicePaymentEmail',
|
||||||
component: InvoicePaymentEmail,
|
component: InvoicePaymentEmail,
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: StoryFn<InvoicePaymentEmailProps> = (args) => (
|
||||||
|
<InvoicePaymentEmail {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Default: StoryFn<InvoicePaymentEmailProps> = Template.bind({});
|
||||||
|
|
||||||
|
Default.args = {
|
||||||
|
// Add default props here
|
||||||
|
invoiceNumber: 'INV-12345',
|
||||||
|
companyName: 'Bigcapital, Inc.',
|
||||||
|
invoiceMessage: `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`,
|
||||||
|
dueDate: ' 10 Oct 2024',
|
||||||
|
total: '$1,000.00',
|
||||||
|
dueAmount: '$1,000.00',
|
||||||
|
items: [{ label: 'Swaniawski Muller', quantity: '1', rate: '$1,000.00' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
const Template: StoryFn<typeof InvoicePaymentEmail> = (
|
|
||||||
args: InvoicePaymentEmailProps
|
|
||||||
) => <InvoicePaymentEmail {...args} />;
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
render,
|
render,
|
||||||
} from '@react-email/components';
|
} from '@react-email/components';
|
||||||
import { CSSProperties } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
|
import { EmailTemplateLayout } from './EmailTemplateLayout';
|
||||||
|
|
||||||
export interface InvoicePaymentEmailProps {
|
export interface InvoicePaymentEmailProps {
|
||||||
preview: string;
|
preview: string;
|
||||||
@@ -96,106 +97,90 @@ export const InvoicePaymentEmail: React.FC<
|
|||||||
items,
|
items,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Html lang="en">
|
<EmailTemplateLayout preview={preview}>
|
||||||
<Head />
|
<Container style={containerStyle}>
|
||||||
<Preview>{preview}</Preview>
|
<Section style={mainSectionStyle}>
|
||||||
|
{companyLogoUri && (
|
||||||
<Tailwind>
|
<Section style={logoSectionStyle}>
|
||||||
<Body style={bodyStyle}>
|
<div
|
||||||
<Container style={containerStyle}>
|
|
||||||
<Section style={mainSectionStyle}>
|
|
||||||
{companyLogoUri && (
|
|
||||||
<Section style={logoSectionStyle}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
...companyLogoStyle,
|
|
||||||
backgroundImage: `url("${companyLogoUri}")`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Image
|
|
||||||
</div>
|
|
||||||
</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={{
|
style={{
|
||||||
...viewInvoiceButtonStyle,
|
...companyLogoStyle,
|
||||||
backgroundColor: primaryColor,
|
backgroundImage: `url("${companyLogoUri}")`,
|
||||||
}}
|
}}
|
||||||
>
|
></div>
|
||||||
{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}>
|
|
||||||
<Column width={'50%'}>
|
|
||||||
<Text style={dueAmountLineItemLabelStyle}>
|
|
||||||
{dueAmountLabel}
|
|
||||||
</Text>
|
|
||||||
</Column>
|
|
||||||
|
|
||||||
<Column width={'50%'}>
|
|
||||||
<Text style={dueAmountLineItemAmountStyle}>
|
|
||||||
{dueAmount}
|
|
||||||
</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>
|
</Section>
|
||||||
</Container>
|
)}
|
||||||
</Body>
|
|
||||||
</Tailwind>
|
<Section style={headerInfoStyle}>
|
||||||
</Html>
|
<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>
|
||||||
|
|
||||||
|
<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}>
|
||||||
|
<Column width={'50%'}>
|
||||||
|
<Text style={dueAmountLineItemLabelStyle}>
|
||||||
|
{dueAmountLabel}
|
||||||
|
</Text>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column width={'50%'}>
|
||||||
|
<Text style={dueAmountLineItemAmountStyle}>{dueAmount}</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>
|
||||||
|
</Container>
|
||||||
|
</EmailTemplateLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -203,14 +188,6 @@ export const renderInvoicePaymentEmail = (props: InvoicePaymentEmailProps) => {
|
|||||||
return render(<InvoicePaymentEmail {...props} />);
|
return render(<InvoicePaymentEmail {...props} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bodyStyle: CSSProperties = {
|
|
||||||
backgroundColor: '#F5F5F5',
|
|
||||||
fontFamily:
|
|
||||||
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
|
|
||||||
|
|
||||||
padding: '40px 0',
|
|
||||||
};
|
|
||||||
|
|
||||||
const containerStyle: CSSProperties = {
|
const containerStyle: CSSProperties = {
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Meta, StoryFn } from '@storybook/react';
|
||||||
|
import {
|
||||||
|
PaymentReceivedEmailTemplateProps,
|
||||||
|
PaymentReceivedEmailTemplate,
|
||||||
|
} from './PaymentReceivedEmailTemplate';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Email/PaymentReceivedEmailTemplate',
|
||||||
|
component: PaymentReceivedEmailTemplate,
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: StoryFn<PaymentReceivedEmailTemplateProps> = (args) => (
|
||||||
|
<PaymentReceivedEmailTemplate {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Default: StoryFn<PaymentReceivedEmailTemplateProps> =
|
||||||
|
Template.bind({});
|
||||||
|
|
||||||
|
Default.args = {};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
export interface PaymentReceivedEmailTemplateProps {
|
||||||
|
preview?: string;
|
||||||
|
|
||||||
|
companyName?: string;
|
||||||
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
primaryColor?: string;
|
||||||
|
|
||||||
|
total: string;
|
||||||
|
totalLabel?: string;
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
|
viewEstimateButtonLabel?: string;
|
||||||
|
viewEstimateButtonUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PaymentReceivedEmailTemplate: React.FC<
|
||||||
|
Readonly<PaymentReceivedEmailTemplateProps>
|
||||||
|
> = ({
|
||||||
|
preview,
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName,
|
||||||
|
companyLogoUri,
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
|
// # invoice total
|
||||||
|
total,
|
||||||
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # View invoice button
|
||||||
|
viewEstimateButtonLabel = 'View Estimate',
|
||||||
|
viewEstimateButtonUrl,
|
||||||
|
}) => {
|
||||||
|
return <h1>asdasd</h1>;
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Meta, StoryFn } from '@storybook/react';
|
||||||
|
import {
|
||||||
|
ReceiptEmailTemplate,
|
||||||
|
ReceiptEmailTemplateProps,
|
||||||
|
} from './ReceiptPaymentEmail';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Email/ReceiptPaymentEmail',
|
||||||
|
component: ReceiptEmailTemplate,
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: StoryFn<ReceiptEmailTemplateProps> = (args) => (
|
||||||
|
<ReceiptEmailTemplate {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Default: StoryFn<ReceiptEmailTemplateProps> = Template.bind({});
|
||||||
|
|
||||||
|
Default.args = {
|
||||||
|
// Add default props here
|
||||||
|
};
|
||||||
45
shared/email-components/src/lib/ReceiptPaymentEmail.tsx
Normal file
45
shared/email-components/src/lib/ReceiptPaymentEmail.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
export interface ReceiptEmailTemplateProps {
|
||||||
|
preview?: string;
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName?: string;
|
||||||
|
companyLogoUri: string;
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor?: string;
|
||||||
|
|
||||||
|
// # Invoice total
|
||||||
|
total: string;
|
||||||
|
totalLabel?: string;
|
||||||
|
|
||||||
|
// # Items
|
||||||
|
items: Array<{ label: string; quantity: string; rate: string }>;
|
||||||
|
|
||||||
|
viewReceiptButtonLabel?: string;
|
||||||
|
viewReceiptButtonUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReceiptEmailTemplate: React.FC<
|
||||||
|
Readonly<ReceiptEmailTemplateProps>
|
||||||
|
> = ({
|
||||||
|
preview,
|
||||||
|
|
||||||
|
// # Company
|
||||||
|
companyName,
|
||||||
|
companyLogoUri,
|
||||||
|
|
||||||
|
// # Colors
|
||||||
|
primaryColor = 'rgb(0, 82, 204)',
|
||||||
|
|
||||||
|
// # Invoice total
|
||||||
|
total,
|
||||||
|
totalLabel = 'Total',
|
||||||
|
|
||||||
|
// # View invoice button
|
||||||
|
viewReceiptButtonLabel = 'View Estimate',
|
||||||
|
viewReceiptButtonUrl,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<h1>asdasd</h1>
|
||||||
|
)
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user