mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
feat: wip send invoice mail preview
This commit is contained in:
@@ -37,8 +37,10 @@ export function ElementCustomizeFieldsMain() {
|
|||||||
<Stack spacing={0} className={styles.mainFields}>
|
<Stack spacing={0} className={styles.mainFields}>
|
||||||
<ElementCustomizeHeader label={'Customize'} />
|
<ElementCustomizeHeader label={'Customize'} />
|
||||||
|
|
||||||
<Stack spacing={0} style={{ flex: '1 1 auto', overflow: 'auto' }}>
|
<Stack spacing={0} flex="1 1 auto" overflow="auto">
|
||||||
<Box style={{ flex: '1 1' }}>{CustomizeTabPanel}</Box>
|
<Box flex={'1 1'} overflow="auto">
|
||||||
|
{CustomizeTabPanel}
|
||||||
|
</Box>
|
||||||
<ElementCustomizeFooterActions />
|
<ElementCustomizeFooterActions />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Box } from '@/components';
|
||||||
|
import { InvoiceMailReceiptPreview } from '../InvoiceCustomize/InvoiceMailReceiptPreview';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
|
import { useInvoiceSendMailBoot } from './InvoiceSendMailContentBoot';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export function InvoiceMailReceiptPreviewConneceted() {
|
||||||
|
const { invoice } = useInvoiceSendMailBoot();
|
||||||
|
|
||||||
|
const items = useMemo(
|
||||||
|
() =>
|
||||||
|
invoice.entries.map((entry: any) => ({
|
||||||
|
quantity: entry.quantity,
|
||||||
|
total: entry.rate_formatted,
|
||||||
|
label: entry.item.name,
|
||||||
|
})),
|
||||||
|
[invoice.entries],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box px={4} pt={8} pb={16}>
|
||||||
|
<InvoiceMailReceiptPreview
|
||||||
|
total={invoice.total_formatted}
|
||||||
|
dueDate={invoice.due_date_formatted}
|
||||||
|
invoiceNumber={invoice.invoice_no}
|
||||||
|
items={items}
|
||||||
|
className={css`
|
||||||
|
margin: 0 auto;
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import React, { createContext, useContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import { Spinner } from '@blueprintjs/core';
|
import { Spinner } from '@blueprintjs/core';
|
||||||
|
import { useInvoice } from '@/hooks/query';
|
||||||
|
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||||
|
|
||||||
interface InvoiceSendMailBootValues {}
|
interface InvoiceSendMailBootValues {
|
||||||
|
invoice: any;
|
||||||
|
isInvoiceLoading: boolean;
|
||||||
|
}
|
||||||
interface InvoiceSendMailBootProps {
|
interface InvoiceSendMailBootProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
@@ -10,12 +16,22 @@ const InvoiceSendMailContentBootContext =
|
|||||||
createContext<InvoiceSendMailBootValues>({} as InvoiceSendMailBootValues);
|
createContext<InvoiceSendMailBootValues>({} as InvoiceSendMailBootValues);
|
||||||
|
|
||||||
export const InvoiceSendMailBoot = ({ children }: InvoiceSendMailBootProps) => {
|
export const InvoiceSendMailBoot = ({ children }: InvoiceSendMailBootProps) => {
|
||||||
const isLoading = false;
|
const {
|
||||||
|
payload: { invoiceId },
|
||||||
|
} = useDrawerContext();
|
||||||
|
|
||||||
|
const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId, {
|
||||||
|
enabled: !!invoiceId,
|
||||||
|
});
|
||||||
|
const isLoading = isInvoiceLoading;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <Spinner size={20} />;
|
return <Spinner size={20} />;
|
||||||
}
|
}
|
||||||
const value = {};
|
const value = {
|
||||||
|
invoice,
|
||||||
|
isInvoiceLoading,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvoiceSendMailContentBootContext.Provider value={value}>
|
<InvoiceSendMailContentBootContext.Provider value={value}>
|
||||||
|
|||||||
@@ -1,13 +1,107 @@
|
|||||||
import { Button, Intent } from "@blueprintjs/core";
|
// @ts-nocheck
|
||||||
import { useFormikContext } from "formik";
|
import { Button, Intent, MenuItem } from '@blueprintjs/core';
|
||||||
import { FFormGroup, FInputGroup, Group, Stack } from "@/components";
|
import { useFormikContext } from 'formik';
|
||||||
import { useDrawerContext } from "@/components/Drawer/DrawerProvider";
|
import {
|
||||||
import { useDrawerActions } from "@/hooks/state";
|
FFormGroup,
|
||||||
|
FInputGroup,
|
||||||
|
FMultiSelect,
|
||||||
|
Group,
|
||||||
|
Stack,
|
||||||
|
} from '@/components';
|
||||||
|
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||||
|
import { useDrawerActions } from '@/hooks/state';
|
||||||
|
|
||||||
|
const commonAddressSelect = {
|
||||||
|
placeholder: '',
|
||||||
|
labelAccessor: '',
|
||||||
|
valueAccessor: 'mail',
|
||||||
|
|
||||||
|
tagAccessor: (item) => `<${item.label}> (${item.mail})`,
|
||||||
|
textAccessor: (item) => `<${item.label}> (${item.mail})`,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create new account renderer.
|
||||||
|
const createNewItemRenderer = (query, active, handleClick) => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
icon="add"
|
||||||
|
text={'Now contact address'}
|
||||||
|
active={active}
|
||||||
|
onClick={handleClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create new item from the given query string.
|
||||||
|
const createNewItemFromQuery = (name) => ({ name });
|
||||||
|
|
||||||
export function InvoiceSendMailFields() {
|
export function InvoiceSendMailFields() {
|
||||||
|
const allowCreate = true;
|
||||||
|
// Maybe inject new item props to select component.
|
||||||
|
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||||
|
const maybeCreateNewItemFromQuery = allowCreate
|
||||||
|
? createNewItemFromQuery
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack bg="white" flex={'1'} spacing={0} borderRight="1px solid #dcdcdd">
|
<Stack
|
||||||
|
bg="white"
|
||||||
|
flex={'1'}
|
||||||
|
maxHeight="100%"
|
||||||
|
spacing={0}
|
||||||
|
borderRight="1px solid #dcdcdd"
|
||||||
|
>
|
||||||
<Stack overflow="auto" flex="1" p={'30px'}>
|
<Stack overflow="auto" flex="1" p={'30px'}>
|
||||||
|
<FFormGroup label={'to'} name={'To'}>
|
||||||
|
<Stack spacing={0}>
|
||||||
|
<FMultiSelect
|
||||||
|
items={[]}
|
||||||
|
name={'to'}
|
||||||
|
popoverProps={{ minimal: true, fill: true }}
|
||||||
|
tagInputProps={{
|
||||||
|
tagProps: { round: true, minimal: true, large: true },
|
||||||
|
large: true,
|
||||||
|
rightElement: (
|
||||||
|
<Group>
|
||||||
|
<a href="#">CC</a>
|
||||||
|
<a href="#">BCC</a>
|
||||||
|
</Group>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
fill={true}
|
||||||
|
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||||
|
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||||
|
{...commonAddressSelect}
|
||||||
|
/>
|
||||||
|
<FMultiSelect
|
||||||
|
items={[]}
|
||||||
|
name={'cc'}
|
||||||
|
popoverProps={{ minimal: true, fill: true }}
|
||||||
|
tagInputProps={{
|
||||||
|
tagProps: { round: true, minimal: true, large: true },
|
||||||
|
large: true,
|
||||||
|
}}
|
||||||
|
fill={true}
|
||||||
|
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||||
|
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||||
|
{...commonAddressSelect}
|
||||||
|
/>
|
||||||
|
<FMultiSelect
|
||||||
|
items={[]}
|
||||||
|
name={'bcc'}
|
||||||
|
popoverProps={{ minimal: true, fill: true }}
|
||||||
|
tagInputProps={{
|
||||||
|
tagProps: { round: true, minimal: true, large: true },
|
||||||
|
large: true,
|
||||||
|
}}
|
||||||
|
fill={true}
|
||||||
|
createNewItemRenderer={maybeCreateNewItemRenderer}
|
||||||
|
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
||||||
|
{...commonAddressSelect}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</FFormGroup>
|
||||||
|
|
||||||
<FFormGroup label={'Submit'} name={'subject'}>
|
<FFormGroup label={'Submit'} name={'subject'}>
|
||||||
<FInputGroup name={'subject'} large />
|
<FInputGroup name={'subject'} large />
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import { css } from '@emotion/css';
|
|||||||
const initialValues = {
|
const initialValues = {
|
||||||
subject: '',
|
subject: '',
|
||||||
message: '',
|
message: '',
|
||||||
to: '',
|
to: [],
|
||||||
cc: '',
|
cc: [],
|
||||||
|
bcc: []
|
||||||
};
|
};
|
||||||
interface InvoiceSendMailFormValues {
|
interface InvoiceSendMailFormValues {
|
||||||
subject: string;
|
subject: string;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Tab, Tabs } from "@blueprintjs/core";
|
import { Tab, Tabs } from '@blueprintjs/core';
|
||||||
import { css } from "@emotion/css";
|
import { css } from '@emotion/css';
|
||||||
import { Box, Stack } from "@/components";
|
import { Stack } from '@/components';
|
||||||
import { InvoiceMailReceiptPreview } from "../InvoiceCustomize/InvoiceMailReceiptPreview";
|
import { InvoiceMailReceiptPreviewConneceted } from './InvoiceMailReceiptPreviewConnected.';
|
||||||
import { InvoicePaperTemplate } from "../InvoiceCustomize/InvoicePaperTemplate";
|
import { InvoiceSendPdfPreviewConnected } from './InvoiceSendPdfPreviewConnected';
|
||||||
|
|
||||||
export function InvoiceSendMailPreview() {
|
export function InvoiceSendMailPreview() {
|
||||||
return (
|
return (
|
||||||
<Stack bg="#F5F5F5" flex={'1'} minWidth="850px">
|
<Stack bg="#F5F5F5" flex={'1'} maxHeight={'100%'} minWidth="850px">
|
||||||
<Tabs
|
<Tabs
|
||||||
id={'preview'}
|
id={'preview'}
|
||||||
defaultSelectedTabId={'payment-page'}
|
defaultSelectedTabId={'payment-page'}
|
||||||
@@ -39,28 +39,12 @@ export function InvoiceSendMailPreview() {
|
|||||||
<Tab
|
<Tab
|
||||||
id={'payment-page'}
|
id={'payment-page'}
|
||||||
title={'Payment page'}
|
title={'Payment page'}
|
||||||
panel={
|
panel={<InvoiceMailReceiptPreviewConneceted />}
|
||||||
<Box px={4} pt={8} pb={16}>
|
|
||||||
<InvoiceMailReceiptPreview
|
|
||||||
className={css`
|
|
||||||
margin: 0 auto;
|
|
||||||
`}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
id="pdf-document"
|
id="pdf-document"
|
||||||
title={'PDF document'}
|
title={'PDF document'}
|
||||||
panel={
|
panel={<InvoiceSendPdfPreviewConnected />}
|
||||||
<Box px={4} py={6}>
|
|
||||||
<InvoicePaperTemplate
|
|
||||||
className={css`
|
|
||||||
margin: 0 auto;
|
|
||||||
`}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Box } from "@/components";
|
||||||
|
import { InvoicePaperTemplate } from "../InvoiceCustomize/InvoicePaperTemplate";
|
||||||
|
import { css } from "@emotion/css";
|
||||||
|
import { useInvoiceSendMailBoot } from "./InvoiceSendMailContentBoot";
|
||||||
|
|
||||||
|
export function InvoiceSendPdfPreviewConnected() {
|
||||||
|
const { invoice } = useInvoiceSendMailBoot();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box px={4} py={6}>
|
||||||
|
<InvoicePaperTemplate
|
||||||
|
dueDate={invoice.due_date_formatted}
|
||||||
|
dateIssue={invoice.invoice_date_formatted}
|
||||||
|
invoiceNumber={invoice.invoice_no}
|
||||||
|
total={invoice.total_formatted}
|
||||||
|
subtotal={invoice.subtotal}
|
||||||
|
discount={''}
|
||||||
|
paymentMade={''}
|
||||||
|
balanceDue={invoice.due_amount_Formatted}
|
||||||
|
statement={invoice.statement}
|
||||||
|
className={css`
|
||||||
|
margin: 0 auto;
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user