From da47418f17640f783ddd525d287c0259f4f56a29 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sat, 23 Nov 2024 20:36:46 +0200 Subject: [PATCH] feat: mail receipt preview --- packages/server/src/models/CreditNote.ts | 13 ++++ packages/server/src/models/PaymentReceive.ts | 13 ++++ .../Estimates/GetSaleEstimateMailState.ts | 3 +- .../GetSaleEstimateMailStateTransformer.ts | 78 +++++++++++++++++-- .../GetPaymentReceivedMailState.tsx | 1 + .../GetPaymentReceivedMailStateTransformer.ts | 44 ++++++++++- .../EstimateSendMailReceipt.tsx | 2 +- .../EstimateSendMailReceiptPreview.tsx | 72 +++++++++++------ .../EstimateSendMailDrawer/_constants.ts | 23 ++++++ .../PaymentReceivedMailPreviewReceipt.tsx | 68 +++++++++++----- .../PaymentReceivedMailDrawer/_constants.ts | 15 ++++ .../ReceiptSendMailPreview.tsx | 71 ++++++++++++----- .../ReceiptSendMailPreviewTabs.tsx | 15 +++- .../ReceiptSendMailReceipt.tsx | 2 +- .../ReceiptSendMailDrawer/_constants.ts | 14 ++++ packages/webapp/src/hooks/query/estimates.tsx | 17 +++- .../src/hooks/query/paymentReceives.tsx | 14 ++++ 17 files changed, 388 insertions(+), 77 deletions(-) create mode 100644 packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/_constants.ts create mode 100644 packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/_constants.ts create mode 100644 packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/_constants.ts diff --git a/packages/server/src/models/CreditNote.ts b/packages/server/src/models/CreditNote.ts index b7400b14e..02c456f9d 100644 --- a/packages/server/src/models/CreditNote.ts +++ b/packages/server/src/models/CreditNote.ts @@ -176,6 +176,7 @@ export default class CreditNote extends mixin(TenantModel, [ const Branch = require('models/Branch'); const Document = require('models/Document'); const Warehouse = require('models/Warehouse'); + const { PdfTemplate } = require('models/PdfTemplate'); return { /** @@ -266,6 +267,18 @@ export default class CreditNote extends mixin(TenantModel, [ query.where('model_ref', 'CreditNote'); }, }, + + /** + * Credit note may belongs to pdf branding template. + */ + pdfTemplate: { + relation: Model.BelongsToOneRelation, + modelClass: PdfTemplate, + join: { + from: 'credit_notes.pdfTemplateId', + to: 'pdf_templates.id', + }, + }, }; } diff --git a/packages/server/src/models/PaymentReceive.ts b/packages/server/src/models/PaymentReceive.ts index daab81d2a..47044f757 100644 --- a/packages/server/src/models/PaymentReceive.ts +++ b/packages/server/src/models/PaymentReceive.ts @@ -61,6 +61,7 @@ export default class PaymentReceive extends mixin(TenantModel, [ const Account = require('models/Account'); const Branch = require('models/Branch'); const Document = require('models/Document'); + const { PdfTemplate } = require('models/PdfTemplate'); return { customer: { @@ -135,6 +136,18 @@ export default class PaymentReceive extends mixin(TenantModel, [ query.where('model_ref', 'PaymentReceive'); }, }, + + /** + * Payment received may belongs to pdf branding template. + */ + pdfTemplate: { + relation: Model.BelongsToOneRelation, + modelClass: PdfTemplate, + join: { + from: 'payment_receives.pdfTemplateId', + to: 'pdf_templates.id', + }, + }, }; } diff --git a/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailState.ts b/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailState.ts index 282e1a542..bc5e2f227 100644 --- a/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailState.ts +++ b/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailState.ts @@ -1,9 +1,10 @@ -import { Inject } from 'typedi'; +import { Inject, Service } from 'typedi'; import { SendSaleEstimateMail } from './SendSaleEstimateMail'; import HasTenancyService from '@/services/Tenancy/TenancyService'; import { GetSaleEstimateMailStateTransformer } from './GetSaleEstimateMailStateTransformer'; import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; +@Service() export class GetSaleEstimateMailState { @Inject() private estimateMail: SendSaleEstimateMail; diff --git a/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailStateTransformer.ts b/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailStateTransformer.ts index 885f02a7c..fbfaf134b 100644 --- a/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailStateTransformer.ts +++ b/packages/server/src/services/Sales/Estimates/GetSaleEstimateMailStateTransformer.ts @@ -9,7 +9,10 @@ export class GetSaleEstimateMailStateTransformer extends SaleEstimateTransfromer public includeAttributes = (): string[] => { return [ 'estimateDate', - 'formattedEstimateDate', + 'estimateDateFormatted', + + 'expirationDate', + 'expirationDateFormatted', 'total', 'totalFormatted', @@ -17,8 +20,7 @@ export class GetSaleEstimateMailStateTransformer extends SaleEstimateTransfromer 'subtotal', 'subtotalFormatted', - 'estimateNo', - + 'estimateNumber', 'entries', 'companyName', @@ -62,10 +64,65 @@ export class GetSaleEstimateMailStateTransformer extends SaleEstimateTransfromer }; /** - * - * @param invoice + * Retrieves the estimate number. + */ + protected estimateDateFormatted = (estimate) => { + return this.formattedEstimateDate(estimate); + }; + + /** + * Retrieves the expiration date of the estimate. + * @param estimate + * @returns {string} + */ + protected expirationDateFormatted = (estimate) => { + return this.formattedExpirationDate(estimate); + }; + + /** + * Retrieves the total amount of the estimate. + * @param estimate * @returns */ + protected total(estimate) { + return estimate.amount; + } + + /** + * Retrieves the subtotal amount of the estimate. + * @param estimate + * @returns {number} + */ + protected subtotal(estimate) { + return estimate.amount; + } + + /** + * Retrieves the formatted total of the estimate. + * @param estimate + * @returns {string} + */ + protected totalFormatted(estimate) { + return this.formatMoney(estimate.amount, { + currencyCode: estimate.currencyCode, + money: true, + }); + } + + /** + * Retrieves the formatted subtotal of the estimate. + * @param estimate + * @returns {string} + */ + protected subtotalFormatted = (estimate) => { + return this.formatNumber(estimate.amount, { money: false }); + }; + + /** + * Retrieves the estimate entries. + * @param invoice + * @returns {Array} + */ protected entries = (invoice) => { return this.item( invoice.entries, @@ -92,9 +149,18 @@ class GetSaleEstimateMailStateEntryTransformer extends ItemEntryTransformer { return ['*']; }; + /** + * Item name. + * @param entry + * @returns + */ + public name = (entry) => { + return entry.item.name; + }; + public includeAttributes = (): string[] => { return [ - 'description', + 'name', 'quantity', 'unitPrice', 'unitPriceFormatted', diff --git a/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailState.tsx b/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailState.tsx index c6411c881..7c6271c71 100644 --- a/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailState.tsx +++ b/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailState.tsx @@ -32,6 +32,7 @@ export class GetPaymentReceivedMailState { .findById(paymentId) .withGraphFetched('customer') .withGraphFetched('entries.invoice') + .withGraphFetched('pdfTemplate') .throwIfNotFound(); const mailOptions = diff --git a/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailStateTransformer.ts b/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailStateTransformer.ts index d52ec279e..f3a922f85 100644 --- a/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailStateTransformer.ts +++ b/packages/server/src/services/Sales/PaymentReceived/GetPaymentReceivedMailStateTransformer.ts @@ -26,7 +26,10 @@ export class GetPaymentReceivedMailStateTransformer extends PaymentReceiveTransf 'total', 'totalFormatted', - 'paymentNo', + 'subtotal', + 'subtotalFormatted', + + 'paymentNumber', 'entries', @@ -87,6 +90,17 @@ export class GetPaymentReceivedMailStateTransformer extends PaymentReceiveTransf return this.formatMoney(payment.paymentAmount); }; + /** + * Retrieves the payment amount. + * @param payment + * @returns {number} + */ + protected total = (payment) => { + return this.formatNumber(payment.amount, { + money: false, + }); + }; + /** * Retrieves the formatted payment amount. * @returns {string} @@ -95,6 +109,34 @@ export class GetPaymentReceivedMailStateTransformer extends PaymentReceiveTransf return this.formatMoney(payment.total); }; + /** + * Retrieves the payment amount. + * @param payment + * @returns {number} + */ + protected subtotal = (payment) => { + return this.formatNumber(payment.amount, { + money: false, + }); + }; + + /** + * Retrieves the formatted payment amount. + * @returns {string} + */ + protected subtotalFormatted = (payment) => { + return this.formatMoney(payment.total); + }; + + /** + * Retrieves the payment number. + * @param payment + * @returns {string} + */ + protected paymentNumber = (payment) => { + return payment.paymentReceiveNo; + }; + /** * Retrieves the payment entries. * @param {IPaymentReceived} payment diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceipt.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceipt.tsx index 69ad4af44..fcf9d8d36 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceipt.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceipt.tsx @@ -5,7 +5,7 @@ import { SendMailReceiptProps, } from '../SendMailViewDrawer/SendMailViewReceiptPreview'; -interface EstimateSendMailReceiptProps extends SendMailReceiptProps { +export interface EstimateSendMailReceiptProps extends SendMailReceiptProps { // # Company name. companyLogoUri?: string; companyName: string; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceiptPreview.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceiptPreview.tsx index 2dca97041..5ead2d7f1 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceiptPreview.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/EstimateSendMailReceiptPreview.tsx @@ -1,39 +1,20 @@ import { css } from '@emotion/css'; -import { EstimateSendMailReceipt } from './EstimateSendMailReceipt'; +import { ComponentType, useMemo } from 'react'; +import { EstimateSendMailReceipt, EstimateSendMailReceiptProps } from './EstimateSendMailReceipt'; import { EstimateSendMailPreviewHeader } from './EstimateSendMailPreviewHeader'; import { Stack } from '@/components'; +import { useEstimateSendMailBoot } from './EstimateSendMailBoot'; +import { useSendEstimateMailMessage } from './hooks'; +import { defaultEstimateMailReceiptProps } from './_constants'; -const defaultEstimateMailReceiptProps = { - companyName: 'Bigcapital Technology, Inc.', - companyLogoUri: ' ', - total: '$1,000.00', - subtotal: '$1,000.00', - estimateNumber: 'INV-0001', - expirationDate: '2 Oct 2024', - dueAmount: '$1,000.00', - items: [{ label: 'Web development', total: '$1000.00', quantity: 1 }], - message: `Hi Ahmed Bouhuolia, - -Here's invoice # INV-00002 for $738.30 - -The amount outstanding of $737.30 is due on 01 Feb 2023. - -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`, -}; export const EstimateSendMailReceiptPreview = () => { return ( - { ); }; + +/** + * Injects props from estimate mail state into the `EstimateSendMailReceipt` component. + */ +const withEstimateMailReceiptPreviewProps = < + P extends EstimateSendMailReceiptProps, +>( + WrappedComponent: ComponentType

, +) => { + return function WithInvoiceMailReceiptPreviewProps(props: P) { + const { estimateMailState } = useEstimateSendMailBoot(); + const message = useSendEstimateMailMessage(); + + const items = useMemo( + () => + estimateMailState?.entries?.map((entry: any) => ({ + quantity: entry.quantity, + total: entry.totalFormatted, + label: entry.name, + })), + [estimateMailState?.entries], + ); + + const mailReceiptPreviewProps = { + ...defaultEstimateMailReceiptProps, + companyName: estimateMailState?.companyName, + companyLogoUri: estimateMailState?.companyLogoUri, + primaryColor: estimateMailState?.primaryColor, + total: estimateMailState?.totalFormatted, + expirationDate: estimateMailState?.expirationDateFormatted, + estimateNumber: estimateMailState?.estimateNumber, + estimateDate: estimateMailState?.estimateDateFormatted, + items, + message + }; + return ; + }; +}; +const EstimateSendMailReceiptConnected = withEstimateMailReceiptPreviewProps( + EstimateSendMailReceipt +); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/_constants.ts b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/_constants.ts new file mode 100644 index 000000000..941bb5a73 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateSendMailDrawer/_constants.ts @@ -0,0 +1,23 @@ +export const defaultEstimateMailReceiptProps = { + companyName: 'Bigcapital Technology, Inc.', + companyLogoUri: ' ', + + total: '$1,000.00', + subtotal: '$1,000.00', + estimateNumber: 'INV-0001', + expirationDate: '2 Oct 2024', + dueAmount: '$1,000.00', + items: [{ label: 'Web development', total: '$1000.00', quantity: 1 }], + message: `Hi Ahmed Bouhuolia, + +Here's invoice # INV-00002 for $738.30 + +The amount outstanding of $737.30 is due on 01 Feb 2023. + +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`, +}; diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/PaymentReceivedMailPreviewReceipt.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/PaymentReceivedMailPreviewReceipt.tsx index f04dbfe6c..31c67222d 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/PaymentReceivedMailPreviewReceipt.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/PaymentReceivedMailPreviewReceipt.tsx @@ -1,23 +1,14 @@ import { css } from '@emotion/css'; -import { PaymentReceivedMailReceipt } from './PaymentReceivedMailReceipt'; +import { ComponentType, useMemo } from 'react'; +import { + PaymentReceivedMailReceipt, + PaymentReceivedMailReceiptProps, +} from './PaymentReceivedMailReceipt'; import { PaymentReceivedMailPreviewHeader } from './PaymentReceivedMailPreviewHeader'; import { Stack } from '@/components'; - -const defaultPaymentReceiptMailProps = { - companyName: 'Company Name', - companyLogoUri: 'https://via.placeholder.com/150', - primaryColor: 'rgb(0, 82, 204)', - paymentDate: '2021-01-01', - paymentDateLabel: 'Payment Date', - total: '100.00', - totalLabel: 'Total', - paymentNumber: '123456', - paymentNumberLabel: 'Payment #', - message: 'Thank you for your payment!', - subtotal: '100.00', - subtotalLabel: 'Subtotal', - items: [{ label: 'Invoice 1', total: '100.00' }], -}; +import { useSendPaymentReceivedtMailMessage } from './_hooks'; +import { usePaymentReceivedSendMailBoot } from './PaymentReceivedMailBoot'; +import { defaultPaymentReceiptMailProps } from './_constants'; export function PaymentReceivedMailPreviewReceipt() { return ( @@ -25,8 +16,7 @@ export function PaymentReceivedMailPreviewReceipt() { - ); } + +/** + * Injects props from invoice mail state into the InvoiceMailReceiptPreview component. + */ +const withPaymentReceivedMailReceiptPreviewProps = < + P extends PaymentReceivedMailReceiptProps, +>( + WrappedComponent: ComponentType

, +) => { + return function WithInvoiceMailReceiptPreviewProps(props: P) { + const message = useSendPaymentReceivedtMailMessage(); + const { paymentReceivedMailState } = usePaymentReceivedSendMailBoot(); + + const items = useMemo( + () => + paymentReceivedMailState?.entries?.map((entry: any) => ({ + quantity: entry.quantity, + total: entry.totalFormatted, + label: entry.name, + })), + [paymentReceivedMailState?.entries], + ); + + const mailPaymentReceivedPreviewProps = { + ...defaultPaymentReceiptMailProps, + companyName: paymentReceivedMailState?.companyName, + companyLogoUri: paymentReceivedMailState?.companyLogoUri, + primaryColor: paymentReceivedMailState?.primaryColor, + total: paymentReceivedMailState?.totalFormatted, + subtotal: paymentReceivedMailState?.subtotalFormatted, + paymentNumber: paymentReceivedMailState?.paymentNumber, + items, + message, + }; + return ; + }; +}; + +export const PaymentReceivedMailReceiptPreviewConnected = + withPaymentReceivedMailReceiptPreviewProps(PaymentReceivedMailReceipt); diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/_constants.ts b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/_constants.ts new file mode 100644 index 000000000..fbcd2759f --- /dev/null +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceivedMailDrawer/_constants.ts @@ -0,0 +1,15 @@ +export const defaultPaymentReceiptMailProps = { + companyName: 'Company Name', + companyLogoUri: 'https://via.placeholder.com/150', + primaryColor: 'rgb(0, 82, 204)', + paymentDate: '2021-01-01', + paymentDateLabel: 'Payment Date', + total: '100.00', + totalLabel: 'Total', + paymentNumber: '123456', + paymentNumberLabel: 'Payment #', + message: 'Thank you for your payment!', + subtotal: '100.00', + subtotalLabel: 'Subtotal', + items: [{ label: 'Invoice 1', total: '100.00' }], +}; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreview.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreview.tsx index 112c70213..ff8d6beb1 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreview.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreview.tsx @@ -1,22 +1,14 @@ +import { ComponentType } from 'react'; +import { css } from '@emotion/css'; import { Stack } from '@/components'; import { ReceiptSendMailPreviewHeader } from './ReceiptSendMailPreviewHeader'; -import { ReceiptSendMailReceipt } from './ReceiptSendMailReceipt'; -import { css } from '@emotion/css'; - -const defaultReceiptMailProps = { - companyLogoUri: 'https://via.placeholder.com/150', - companyName: 'Company Name', - receiptNumber: '1234', - total: '1000', - message: 'Thank you for your business!', - items: [ - { label: 'Item 1', quantity: 1, total: '500' }, - { label: 'Item 2', quantity: 2, total: '500' }, - ], - subtotal: '1000', - showViewReceiptButton: true, - viewReceiptButtonLabel: 'View Receipt', -}; +import { + ReceiptSendMailReceipt, + ReceiptSendMailReceiptProps, +} from './ReceiptSendMailReceipt'; +import { defaultReceiptMailProps } from './_constants'; +import { useReceiptSendMailBoot } from './ReceiptSendMailBoot'; +import { useSendReceiptMailMessage } from './_hooks'; export function ReceiptSendMailPreview() { return ( @@ -24,8 +16,7 @@ export function ReceiptSendMailPreview() { - ); } + +/** + * Injects props from receipt mail state into the `ReceiptMailPreviewConnected` component. + */ +const withReceiptMailReceiptPreviewProps = < + P extends ReceiptSendMailReceiptProps, +>( + WrappedComponent: ComponentType

, +) => { + return function WithInvoiceMailReceiptPreviewProps(props: P) { + const message = useSendReceiptMailMessage(); + const { receiptMailState } = useReceiptSendMailBoot(); + + // const items = useMemo( + // () => + // invoiceMailState?.entries?.map((entry: any) => ({ + // quantity: entry.quantity, + // total: entry.totalFormatted, + // label: entry.name, + // })), + // [invoiceMailState?.entries], + // ); + + const mailReceiptPreviewProps = { + ...defaultReceiptMailProps, + // companyName: receiptMailState?.companyName, + // companyLogoUri: receiptMailState?.companyLogoUri, + // primaryColor: receiptMailState?.primaryColor, + // total: receiptMailState?.totalFormatted, + // dueDate: receiptMailState?.dueDateFormatted, + // dueAmount: invoiceMailState?.dueAmountFormatted, + // invoiceNumber: invoiceMailState?.invoiceNo, + // items, + message, + }; + return ; + }; +}; + +export const ReceiptMailPreviewConnected = withReceiptMailReceiptPreviewProps( + ReceiptSendMailReceipt, +); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreviewTabs.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreviewTabs.tsx index 7b8112e79..9cf039bce 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreviewTabs.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailPreviewTabs.tsx @@ -1,8 +1,17 @@ -import { Suspense } from 'react'; +import { lazy, Suspense } from 'react'; import { Tab } from '@blueprintjs/core'; import { SendMailViewPreviewTabs } from '../../Estimates/SendMailViewDrawer/SendMailViewPreviewTabs'; -import { ReceiptSendMailPreview } from './ReceiptSendMailPreview'; -import { ReceiptSendMailPdfPreview } from './ReceiptSendMailPdfPreview'; + +const ReceiptSendMailPreview = lazy(() => + import('./ReceiptSendMailPreview').then((module) => ({ + default: module.ReceiptSendMailPreview, + })), +); +const ReceiptSendMailPdfPreview = lazy(() => + import('./ReceiptSendMailPdfPreview').then((module) => ({ + default: module.ReceiptSendMailPdfPreview, + })), +); export function ReceiptSendMailPreviewTabs() { return ( diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailReceipt.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailReceipt.tsx index bd0517a96..75032a1fe 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailReceipt.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/ReceiptSendMailReceipt.tsx @@ -5,7 +5,7 @@ import { SendMailReceiptProps, } from '../../Estimates/SendMailViewDrawer/SendMailViewReceiptPreview'; -interface ReceiptSendMailReceiptProps extends SendMailReceiptProps { +export interface ReceiptSendMailReceiptProps extends SendMailReceiptProps { // # Company name. companyLogoUri?: string; companyName: string; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/_constants.ts b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/_constants.ts new file mode 100644 index 000000000..de2db7030 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptSendMailDrawer/_constants.ts @@ -0,0 +1,14 @@ +export const defaultReceiptMailProps = { + companyLogoUri: 'https://via.placeholder.com/150', + companyName: 'Company Name', + receiptNumber: '1234', + total: '1000', + message: 'Thank you for your business!', + items: [ + { label: 'Item 1', quantity: 1, total: '500' }, + { label: 'Item 2', quantity: 2, total: '500' }, + ], + subtotal: '1000', + showViewReceiptButton: true, + viewReceiptButtonLabel: 'View Receipt', +}; diff --git a/packages/webapp/src/hooks/query/estimates.tsx b/packages/webapp/src/hooks/query/estimates.tsx index 82255c4b3..bb111f07d 100644 --- a/packages/webapp/src/hooks/query/estimates.tsx +++ b/packages/webapp/src/hooks/query/estimates.tsx @@ -269,12 +269,27 @@ export interface SaleEstimateMailStateResponse { companyName: string; customerName: string; entries: Array; + estimateDate: string; + estimateDateFormatted: string; + + expirationDate: string; + expirationDateFormatted: string; + + primaryColor: string; + + total: number; + totalFormatted: string; + + subtotal: number; + subtotalFormatted: string; + + estimateNumber: string; + formatArgs: { customerName: string; estimateAmount: string; }; - formattedEstimateDate: string; from: Array; fromOptions: Array; message: string; diff --git a/packages/webapp/src/hooks/query/paymentReceives.tsx b/packages/webapp/src/hooks/query/paymentReceives.tsx index 3b3112d6e..017239f18 100644 --- a/packages/webapp/src/hooks/query/paymentReceives.tsx +++ b/packages/webapp/src/hooks/query/paymentReceives.tsx @@ -264,15 +264,29 @@ export function useSendPaymentReceiveMail(props) { export interface GetPaymentReceivedMailStateResponse { companyName: string; customerName: string; + entries: Array<{ paymentAmountFormatted: string }>; + from: Array; fromOptions: Array<{ mail: string; label: string; primary: boolean }>; + paymentAmountFormatted: string; + paymentDate: string; paymentDateFormatted: string; + to: Array; toOptions: Array<{ mail: string; label: string; primary: boolean }>; + + total: number; totalFormatted: string; + + subtotal: number; + subtotalFormatted: string; + + paymentNumber: string; + companyLogoUri?: string; + primaryColor?: string; } export function usePaymentReceivedMailState(