mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
Merge branch 'develop' into add-pdf-templates-package
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"dependencies": {
|
||||
"@bigcapital/utils": "*",
|
||||
"@bigcapital/pdf-templates": "*",
|
||||
"@blueprintjs-formik/core": "^0.3.6",
|
||||
"@blueprintjs-formik/core": "^0.3.7",
|
||||
"@blueprintjs-formik/datetime": "^0.3.7",
|
||||
"@blueprintjs-formik/select": "^0.3.5",
|
||||
"@blueprintjs/colors": "4.1.19",
|
||||
|
||||
@@ -93,6 +93,7 @@ export function InvoiceMailReceipt({
|
||||
h="90px"
|
||||
w="90px"
|
||||
mx="auto"
|
||||
borderRadius="3px"
|
||||
backgroundRepeat="no-repeat"
|
||||
backgroundPosition="center center"
|
||||
backgroundSize="contain"
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { Box, } from '@/components';
|
||||
import { InvoiceMailReceiptPreview } from '../InvoiceCustomize/InvoiceMailReceiptPreview';
|
||||
import { useInvoiceSendMailBoot } from './InvoiceSendMailContentBoot';
|
||||
import { InvoiceSendMailPreviewWithHeader } from './InvoiceSendMailHeaderPreview';
|
||||
import { useSendInvoiceMailMessage } from './_hooks';
|
||||
|
||||
export function InvoiceMailReceiptPreviewConneceted() {
|
||||
const mailMessage = useSendInvoiceMailMessage();
|
||||
const { invoiceMailState } = useInvoiceSendMailBoot();
|
||||
|
||||
const items = useMemo(
|
||||
() =>
|
||||
invoiceMailState?.entries?.map((entry: any) => ({
|
||||
quantity: entry.quantity,
|
||||
total: entry.totalFormatted,
|
||||
label: entry.name,
|
||||
})),
|
||||
[invoiceMailState?.entries],
|
||||
);
|
||||
|
||||
return (
|
||||
<InvoiceSendMailPreviewWithHeader>
|
||||
<Box px={4} pt={8} pb={16}>
|
||||
<InvoiceMailReceiptPreview
|
||||
companyName={invoiceMailState?.companyName}
|
||||
// companyLogoUri={invoiceMailState?.companyLogoUri}
|
||||
|
||||
primaryColor={invoiceMailState?.primaryColor}
|
||||
total={invoiceMailState?.totalFormatted}
|
||||
dueDate={invoiceMailState?.dueDateFormatted}
|
||||
dueAmount={invoiceMailState?.dueAmountFormatted}
|
||||
|
||||
invoiceNumber={invoiceMailState?.invoiceNo}
|
||||
items={items}
|
||||
message={mailMessage}
|
||||
className={css`
|
||||
margin: 0 auto;
|
||||
`}
|
||||
/>
|
||||
</Box>
|
||||
</InvoiceSendMailPreviewWithHeader>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { useMemo, ComponentType } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { Box } from '@/components';
|
||||
import {
|
||||
InvoiceMailReceiptPreview,
|
||||
InvoiceMailReceiptPreviewProps,
|
||||
} from '../InvoiceCustomize/InvoiceMailReceiptPreview';
|
||||
import { useInvoiceSendMailBoot } from './InvoiceSendMailContentBoot';
|
||||
import { InvoiceSendMailPreviewWithHeader } from './InvoiceSendMailHeaderPreview';
|
||||
import { useSendInvoiceMailMessage } from './_hooks';
|
||||
|
||||
export function InvoiceMailReceiptPreviewConnected() {
|
||||
return (
|
||||
<InvoiceSendMailPreviewWithHeader>
|
||||
<Box px={4} pt={8} pb={16}>
|
||||
<InvoiceMailReceiptPreviewWithProps
|
||||
className={css`
|
||||
margin: 0 auto;
|
||||
`}
|
||||
/>
|
||||
</Box>
|
||||
</InvoiceSendMailPreviewWithHeader>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects props from invoice mail state into the InvoiceMailReceiptPreview component.
|
||||
*/
|
||||
const withInvoiceMailReceiptPreviewProps = <
|
||||
P extends InvoiceMailReceiptPreviewProps,
|
||||
>(
|
||||
WrappedComponent: ComponentType<P & InvoiceMailReceiptPreviewProps>,
|
||||
) => {
|
||||
return function WithInvoiceMailReceiptPreviewProps(props: P) {
|
||||
const message = useSendInvoiceMailMessage();
|
||||
const { invoiceMailState } = useInvoiceSendMailBoot();
|
||||
|
||||
const items = useMemo(
|
||||
() =>
|
||||
invoiceMailState?.entries?.map((entry: any) => ({
|
||||
quantity: entry.quantity,
|
||||
total: entry.totalFormatted,
|
||||
label: entry.name,
|
||||
})),
|
||||
[invoiceMailState?.entries],
|
||||
);
|
||||
|
||||
const mailReceiptPreviewProps = {
|
||||
companyName: invoiceMailState?.companyName,
|
||||
companyLogoUri: invoiceMailState?.companyLogoUri,
|
||||
primaryColor: invoiceMailState?.primaryColor,
|
||||
total: invoiceMailState?.totalFormatted,
|
||||
dueDate: invoiceMailState?.dueDateFormatted,
|
||||
dueAmount: invoiceMailState?.dueAmountFormatted,
|
||||
invoiceNumber: invoiceMailState?.invoiceNo,
|
||||
items,
|
||||
message,
|
||||
};
|
||||
return <WrappedComponent {...mailReceiptPreviewProps} {...props} />;
|
||||
};
|
||||
};
|
||||
|
||||
export const InvoiceMailReceiptPreviewWithProps =
|
||||
withInvoiceMailReceiptPreviewProps(InvoiceMailReceiptPreview);
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-nocheck
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { Drawer, DrawerSuspense } from '@/components';
|
||||
import withDrawers from '@/containers/Drawer/withDrawers';
|
||||
import React from 'react';
|
||||
|
||||
const InvoiceSendMailContent = React.lazy(() =>
|
||||
import('./InvoiceSendMailContent').then((module) => ({
|
||||
|
||||
@@ -18,9 +18,14 @@ import {
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useDrawerActions } from '@/hooks/state';
|
||||
import { useInvoiceMailItems, useSendInvoiceFormatArgsOptions } from './_hooks';
|
||||
import { InvoiceSendMailFormValues } from './_types';
|
||||
|
||||
// Create new account renderer.
|
||||
const createNewItemRenderer = (query, active, handleClick) => {
|
||||
const createNewItemRenderer = (
|
||||
query: string,
|
||||
active: boolean,
|
||||
handleClick: React.MouseEventHandler<HTMLElement>,
|
||||
) => {
|
||||
return (
|
||||
<MenuItem
|
||||
icon="add"
|
||||
@@ -32,7 +37,7 @@ const createNewItemRenderer = (query, active, handleClick) => {
|
||||
};
|
||||
|
||||
// Create new item from the given query string.
|
||||
const createNewItemFromQuery = (name) => ({ name });
|
||||
const createNewItemFromQuery = (text: string): SelectOptionProps => ({ text });
|
||||
|
||||
const styleEmailButton = css`
|
||||
&.bp4-button.bp4-small {
|
||||
@@ -62,19 +67,19 @@ export function InvoiceSendMailFields() {
|
||||
const [showCCField, setShowCCField] = useState<boolean>(false);
|
||||
const [showBccField, setShowBccField] = useState<boolean>(false);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
const { values, setFieldValue } =
|
||||
useFormikContext<InvoiceSendMailFormValues>();
|
||||
const items = useInvoiceMailItems();
|
||||
const argsOptions = useSendInvoiceFormatArgsOptions();
|
||||
|
||||
const handleClickCcBtn = (event) => {
|
||||
const handleClickCcBtn = (event: React.MouseEvent<HTMLElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
setShowCCField(true);
|
||||
};
|
||||
|
||||
const handleClickBccBtn = (event) => {
|
||||
const handleClickBccBtn = (event: React.MouseEvent<HTMLElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -82,64 +87,71 @@ export function InvoiceSendMailFields() {
|
||||
};
|
||||
|
||||
const handleCreateToItemSelect = (value: SelectOptionProps) => {
|
||||
setFieldValue('to', [...values?.to, value?.name]);
|
||||
setFieldValue('to', [...values?.to, value?.text]);
|
||||
};
|
||||
|
||||
const handleCreateCcItemSelect = (value: SelectOptionProps) => {
|
||||
setFieldValue('cc', [...values?.cc, value?.name]);
|
||||
setFieldValue('cc', [...values?.cc, value?.text]);
|
||||
};
|
||||
|
||||
const handleCreateBccItemSelect = (value: SelectOptionProps) => {
|
||||
setFieldValue('bcc', [...values?.bcc, value?.name]);
|
||||
setFieldValue('bcc', [...values?.bcc, value?.text]);
|
||||
};
|
||||
|
||||
const rightElementsToField = useMemo(() => (
|
||||
<Group
|
||||
spacing={0}
|
||||
paddingRight={'7px'}
|
||||
paddingTop={'7px'}
|
||||
fontWeight={500}
|
||||
color={'#000'}
|
||||
>
|
||||
<Button
|
||||
onClick={handleClickCcBtn}
|
||||
minimal
|
||||
small
|
||||
className={styleEmailButton}
|
||||
const rightElementsToField = useMemo(
|
||||
() => (
|
||||
<Group
|
||||
spacing={0}
|
||||
paddingRight={'7px'}
|
||||
paddingTop={'7px'}
|
||||
fontWeight={500}
|
||||
color={'#000'}
|
||||
>
|
||||
CC
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleClickCcBtn}
|
||||
minimal
|
||||
small
|
||||
className={styleEmailButton}
|
||||
>
|
||||
CC
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={handleClickBccBtn}
|
||||
minimal
|
||||
small
|
||||
className={styleEmailButton}
|
||||
>
|
||||
BCC
|
||||
</Button>
|
||||
</Group>
|
||||
), []);
|
||||
<Button
|
||||
onClick={handleClickBccBtn}
|
||||
minimal
|
||||
small
|
||||
className={styleEmailButton}
|
||||
>
|
||||
BCC
|
||||
</Button>
|
||||
</Group>
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
const handleTextareaChange = useCallback((item: SelectOptionProps) => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
const handleTextareaChange = useCallback(
|
||||
(item: SelectOptionProps) => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
|
||||
const { selectionStart, selectionEnd, value: text } = textarea;
|
||||
const insertText = `{${item.value}}`;
|
||||
const message =
|
||||
text.substring(0, selectionStart) +
|
||||
insertText +
|
||||
text.substring(selectionEnd);
|
||||
const { selectionStart, selectionEnd, value: text } = textarea;
|
||||
const insertText = `{${item.value}}`;
|
||||
const message =
|
||||
text.substring(0, selectionStart) +
|
||||
insertText +
|
||||
text.substring(selectionEnd);
|
||||
|
||||
setFieldValue('message', message);
|
||||
setFieldValue('message', message);
|
||||
|
||||
// Move the cursor to the end of the inserted text
|
||||
setTimeout(() => {
|
||||
textarea.selectionStart = textarea.selectionEnd =
|
||||
selectionStart + insertText.length;
|
||||
textarea.focus();
|
||||
}, 0);
|
||||
}, [setFieldValue]);
|
||||
// Move the cursor to the end of the inserted text
|
||||
setTimeout(() => {
|
||||
textarea.selectionStart = textarea.selectionEnd =
|
||||
selectionStart + insertText.length;
|
||||
textarea.focus();
|
||||
}, 0);
|
||||
},
|
||||
[setFieldValue],
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -233,7 +245,7 @@ export function InvoiceSendMailFields() {
|
||||
position: Position.BOTTOM_LEFT,
|
||||
minimal: true,
|
||||
}}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
input={() => (
|
||||
<Button
|
||||
minimal
|
||||
rightIcon={
|
||||
|
||||
@@ -3,9 +3,9 @@ import { css } from '@emotion/css';
|
||||
import { Tab, Tabs } from '@blueprintjs/core';
|
||||
import { Stack } from '@/components';
|
||||
|
||||
const InvoiceMailReceiptPreviewConneceted = lazy(() =>
|
||||
import('./InvoiceMailReceiptPreviewConnected.').then((module) => ({
|
||||
default: module.InvoiceMailReceiptPreviewConneceted,
|
||||
const InvoiceMailReceiptPreviewConnected = lazy(() =>
|
||||
import('./InvoiceMailReceiptPreviewConnected').then((module) => ({
|
||||
default: module.InvoiceMailReceiptPreviewConnected,
|
||||
})),
|
||||
);
|
||||
const InvoiceSendPdfPreviewConnected = lazy(() =>
|
||||
@@ -51,7 +51,7 @@ export function InvoiceSendMailPreview() {
|
||||
title={'Payment page'}
|
||||
panel={
|
||||
<Suspense>
|
||||
<InvoiceMailReceiptPreviewConneceted />
|
||||
<InvoiceMailReceiptPreviewConnected />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -372,6 +372,7 @@ export function useSendSaleInvoiceMail(
|
||||
// --------------------------------------
|
||||
export interface GetSaleInvoiceDefaultOptionsResponse {
|
||||
companyName: string;
|
||||
companyLogoUri: string;
|
||||
|
||||
dueDate: string;
|
||||
dueDateFormatted: string;
|
||||
|
||||
Reference in New Issue
Block a user