mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
feat: wip invoice mail receipt preview
This commit is contained in:
@@ -1,11 +1,5 @@
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { Spinner, Tab } from '@blueprintjs/core';
|
||||
import {
|
||||
InvoicePaperTemplate,
|
||||
InvoicePaperTemplateProps,
|
||||
} from './InvoicePaperTemplate';
|
||||
import {
|
||||
ElementCustomize,
|
||||
ElementCustomizeContent,
|
||||
@@ -17,21 +11,26 @@ import { InvoiceCustomizeSchema } from './InvoiceCustomizeForm.schema';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useDrawerActions } from '@/hooks/state';
|
||||
import { BrandingTemplateForm } from '@/containers/BrandingTemplates/BrandingTemplateForm';
|
||||
import { useElementCustomizeContext } from '@/containers/ElementCustomize/ElementCustomizeProvider';
|
||||
import { initialValues } from './constants';
|
||||
import { useIsTemplateNamedFilled } from '@/containers/BrandingTemplates/utils';
|
||||
import { InvoiceCustomizeTabs } from './InvoiceCustomizeTabs';
|
||||
|
||||
const InvoicePaymentPagePreview = lazy(() =>
|
||||
import('@/containers/PaymentPortal/InvoicePaymentPagePreview').then(
|
||||
(module) => ({ default: module.InvoicePaymentPagePreview }),
|
||||
),
|
||||
const InvoiceCustomizePaymentPreview = lazy(() =>
|
||||
import('./InvoiceCustomizePaymentPreview').then((module) => ({
|
||||
default: module.InvoiceCustomizePaymentPreview,
|
||||
})),
|
||||
);
|
||||
|
||||
const InvoiceMailReceiptPreview = lazy(() =>
|
||||
import(
|
||||
'@/containers/Sales/Invoices/InvoiceCustomize/InvoiceMailReceiptPreview'
|
||||
).then((module) => ({ default: module.InvoiceMailReceiptPreview })),
|
||||
const InvoiceCustomizeMailReceiptPreview = lazy(() =>
|
||||
import('./InvoiceCustomizeMailReceiptPreview').then((module) => ({
|
||||
default: module.InvoiceCustomizeMailReceiptPreview,
|
||||
})),
|
||||
);
|
||||
|
||||
const InvoiceCustomizePdfPreview = lazy(() =>
|
||||
import('./InvoiceCustomizePdfPreview').then((module) => ({
|
||||
default: module.InvoiceCustomizePdfPreview,
|
||||
})),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -80,7 +79,7 @@ function InvoiceCustomizeFormContent() {
|
||||
title={'PDF document'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoicePaperTemplateFormConnected />
|
||||
<InvoiceCustomizePdfPreview />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
@@ -89,7 +88,7 @@ function InvoiceCustomizeFormContent() {
|
||||
title={'Payment page'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoicePaymentPagePreview />
|
||||
<InvoiceCustomizePaymentPreview />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
@@ -98,7 +97,7 @@ function InvoiceCustomizeFormContent() {
|
||||
title={'Email receipt'}
|
||||
panel={
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<InvoiceMailReceiptPreview mx={'auto'} />
|
||||
<InvoiceCustomizeMailReceiptPreview mx={'auto'} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
@@ -119,27 +118,3 @@ function InvoiceCustomizeFormContent() {
|
||||
</ElementCustomizeContent>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the `InvoicePaperTemplate` component props from the form and branding states.
|
||||
* @param Component
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const withInvoicePreviewTemplateProps = <P extends object>(
|
||||
Component: React.ComponentType<P>,
|
||||
) => {
|
||||
return (props: Omit<P, keyof InvoicePaperTemplateProps>) => {
|
||||
const { values } = useFormikContext<InvoiceCustomizeFormValues>();
|
||||
const { brandingState } = useElementCustomizeContext();
|
||||
|
||||
const mergedProps: InvoicePaperTemplateProps = {
|
||||
...brandingState,
|
||||
...values,
|
||||
};
|
||||
return <Component {...(props as P)} {...mergedProps} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoicePaperTemplateFormConnected = R.compose(
|
||||
withInvoicePreviewTemplateProps,
|
||||
)(InvoicePaperTemplate);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { Classes, Text } from '@blueprintjs/core';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
FFormGroup,
|
||||
FieldRequiredHint,
|
||||
@@ -13,7 +14,6 @@ import { CreditCardIcon } from '@/icons/CreditCardIcon';
|
||||
import { Overlay } from './Overlay';
|
||||
import { useIsTemplateNamedFilled } from '@/containers/BrandingTemplates/utils';
|
||||
import { BrandingCompanyLogoUploadField } from '@/containers/ElementCustomize/components/BrandingCompanyLogoUploadField';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { MANAGE_LINK_URL } from './constants';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useDrawerActions } from '@/hooks/state';
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as R from 'ramda';
|
||||
import { InvoicePaymentPagePreviewProps } from '@/containers/PaymentPortal/InvoicePaymentPagePreview';
|
||||
import { InvoiceCustomizeFormValues } from './types';
|
||||
import { useElementCustomizeContext } from '@/containers/ElementCustomize/ElementCustomizeProvider';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { InvoiceMailReceiptPreview } from './InvoiceMailReceiptPreview';
|
||||
|
||||
const withInvoiceMailReceiptPreviewConnected = <P extends Object>(
|
||||
Component: React.ComponentType<P>,
|
||||
) => {
|
||||
return (props: Omit<P, keyof InvoicePaymentPagePreviewProps>) => {
|
||||
const { values } = useFormikContext<InvoiceCustomizeFormValues>();
|
||||
const { brandingState } = useElementCustomizeContext();
|
||||
|
||||
const mergedBrandingState = {
|
||||
...brandingState,
|
||||
...values,
|
||||
};
|
||||
const mergedProps: InvoicePaymentPagePreviewProps = {
|
||||
companyLogoUri: mergedBrandingState?.companyLogoUri,
|
||||
primaryColor: mergedBrandingState?.primaryColor,
|
||||
// organizationAddress: mergedBrandingState,
|
||||
};
|
||||
return <Component {...(props as P)} {...mergedProps} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoiceCustomizeMailReceiptPreview = R.compose(
|
||||
withInvoiceMailReceiptPreviewConnected,
|
||||
)(InvoiceMailReceiptPreview);
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import {
|
||||
InvoicePaymentPagePreview,
|
||||
InvoicePaymentPagePreviewProps,
|
||||
} from '@/containers/PaymentPortal/InvoicePaymentPagePreview';
|
||||
import { useElementCustomizeContext } from '@/containers/ElementCustomize/ElementCustomizeProvider';
|
||||
import { InvoiceCustomizeFormValues } from './types';
|
||||
|
||||
const withInvoicePaymentPreviewPageProps = <P extends Object>(
|
||||
Component: React.ComponentType<P>,
|
||||
) => {
|
||||
return (props: Omit<P, keyof InvoicePaymentPagePreviewProps>) => {
|
||||
const { values } = useFormikContext<InvoiceCustomizeFormValues>();
|
||||
const { brandingState } = useElementCustomizeContext();
|
||||
|
||||
const mergedBrandingState = {
|
||||
...brandingState,
|
||||
...values,
|
||||
};
|
||||
const mergedProps: InvoicePaymentPagePreviewProps = {
|
||||
companyLogoUri: mergedBrandingState?.companyLogoUri,
|
||||
primaryColor: mergedBrandingState?.primaryColor,
|
||||
};
|
||||
return <Component {...(props as P)} {...mergedProps} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoiceCustomizePaymentPreview = R.compose(
|
||||
withInvoicePaymentPreviewPageProps,
|
||||
)(InvoicePaymentPagePreview);
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import {
|
||||
InvoicePaperTemplate,
|
||||
InvoicePaperTemplateProps,
|
||||
} from './InvoicePaperTemplate';
|
||||
import { useElementCustomizeContext } from '@/containers/ElementCustomize/ElementCustomizeProvider';
|
||||
import { InvoiceCustomizeFormValues } from './types';
|
||||
|
||||
/**
|
||||
* Injects the `InvoicePaperTemplate` component props from the form and branding states.
|
||||
* @param Component
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const withInvoicePreviewTemplateProps = <P extends object>(
|
||||
Component: React.ComponentType<P>,
|
||||
) => {
|
||||
return (props: Omit<P, keyof InvoicePaperTemplateProps>) => {
|
||||
const { values } = useFormikContext<InvoiceCustomizeFormValues>();
|
||||
const { brandingState } = useElementCustomizeContext();
|
||||
|
||||
const mergedProps: InvoicePaperTemplateProps = {
|
||||
...brandingState,
|
||||
...values,
|
||||
};
|
||||
return <Component {...(props as P)} {...mergedProps} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoiceCustomizePdfPreview = R.compose(
|
||||
withInvoicePreviewTemplateProps,
|
||||
)(InvoicePaperTemplate);
|
||||
@@ -4,35 +4,75 @@ import { x } from '@xstyled/emotion';
|
||||
import { Group, Stack, StackProps } from '@/components';
|
||||
|
||||
export interface InvoiceMailReceiptProps extends StackProps {
|
||||
companyLogoUri?: string;
|
||||
message: string;
|
||||
// # Company
|
||||
companyName: string;
|
||||
invoiceNumber: string;
|
||||
companyLogoUri?: string;
|
||||
|
||||
// # Colors
|
||||
primaryColor?: string,
|
||||
|
||||
// # Due date
|
||||
dueDate: string;
|
||||
items?: Array<{ label: string; total: string; quantity: string | number }>;
|
||||
total: string;
|
||||
dueAmount: string;
|
||||
totalLabel?: string;
|
||||
dueDateLabel?: string;
|
||||
|
||||
// # Due amount
|
||||
dueAmountLabel?: string;
|
||||
dueAmount: string;
|
||||
|
||||
// # Total
|
||||
total: string;
|
||||
totalLabel?: string;
|
||||
|
||||
// # Invoice number
|
||||
invoiceNumber: string;
|
||||
invoiceNumberLabel?: string;
|
||||
|
||||
// # Mail message
|
||||
message: string;
|
||||
|
||||
// # Invoice items
|
||||
items?: Array<{ label: string; total: string; quantity: string | number }>;
|
||||
|
||||
// # View invoice button
|
||||
showViewInvoiceButton?: boolean;
|
||||
viewInvoiceButtonLabel?: string;
|
||||
viewInvoiceButtonOnClick?: () => void;
|
||||
invoiceNumberLabel?: string;
|
||||
}
|
||||
|
||||
export function InvoiceMailReceipt({
|
||||
companyLogoUri,
|
||||
message,
|
||||
// Company
|
||||
companyName,
|
||||
total,
|
||||
invoiceNumber,
|
||||
companyLogoUri,
|
||||
|
||||
// # Colors
|
||||
primaryColor,
|
||||
|
||||
// Due date
|
||||
dueDate,
|
||||
dueDateLabel = 'Due',
|
||||
|
||||
// Due amount
|
||||
dueAmountLabel = 'Due Amount',
|
||||
dueAmount,
|
||||
|
||||
// Total
|
||||
total,
|
||||
totalLabel = 'Total',
|
||||
|
||||
// Invoice number
|
||||
invoiceNumber,
|
||||
invoiceNumberLabel = 'Invoice #',
|
||||
|
||||
// Invoice message
|
||||
message,
|
||||
|
||||
// Invoice items
|
||||
items,
|
||||
|
||||
// View invoice button
|
||||
showViewInvoiceButton = true,
|
||||
viewInvoiceButtonLabel = 'View Invoice',
|
||||
viewInvoiceButtonOnClick,
|
||||
totalLabel = 'Total',
|
||||
dueAmountLabel = 'Due Amount',
|
||||
invoiceNumberLabel = 'Invoice #',
|
||||
...restProps
|
||||
}: InvoiceMailReceiptProps) {
|
||||
return (
|
||||
@@ -48,7 +88,15 @@ export function InvoiceMailReceipt({
|
||||
>
|
||||
<Stack spacing={16} textAlign={'center'}>
|
||||
{companyLogoUri && (
|
||||
<x.div h={'90px'} w={'90px'} bg="#F2F2F2" mx="auto"></x.div>
|
||||
<x.div
|
||||
h="90px"
|
||||
w="90px"
|
||||
mx="auto"
|
||||
backgroundRepeat="no-repeat"
|
||||
backgroundPosition="center center"
|
||||
backgroundSize="contain"
|
||||
backgroundImage={`url("${companyLogoUri}")`}
|
||||
></x.div>
|
||||
)}
|
||||
<Stack spacing={8}>
|
||||
<x.h1 m={0} fontSize={'18px'} fontWeight={500} color="#404854">
|
||||
@@ -64,7 +112,7 @@ export function InvoiceMailReceipt({
|
||||
</x.span>
|
||||
|
||||
<x.span fontSize={'13px'} color="#404854">
|
||||
Due {dueDate}
|
||||
{dueDateLabel} {dueDate}
|
||||
</x.span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
@@ -73,18 +121,23 @@ export function InvoiceMailReceipt({
|
||||
{message}
|
||||
</x.p>
|
||||
|
||||
<Button
|
||||
large
|
||||
intent={Intent.PRIMARY}
|
||||
className={css`
|
||||
&.bp4-large {
|
||||
min-height: 38px;
|
||||
}
|
||||
`}
|
||||
onClick={viewInvoiceButtonOnClick}
|
||||
>
|
||||
{viewInvoiceButtonLabel}
|
||||
</Button>
|
||||
{showViewInvoiceButton && (
|
||||
<Button
|
||||
large
|
||||
intent={Intent.PRIMARY}
|
||||
className={css`
|
||||
&.bp4-intent-primary{
|
||||
background-color: ${primaryColor};
|
||||
}
|
||||
&.bp4-large {
|
||||
min-height: 38px;
|
||||
}
|
||||
`}
|
||||
onClick={viewInvoiceButtonOnClick}
|
||||
>
|
||||
{viewInvoiceButtonLabel}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Stack spacing={0}>
|
||||
{items?.map((item, key) => (
|
||||
|
||||
Reference in New Issue
Block a user