mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
feat: wip send invoice preview
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import { Classes, Text } from '@blueprintjs/core';
|
||||
import { PaperTemplate, PaperTemplateTotalBorder } from './PaperTemplate';
|
||||
import {
|
||||
PaperTemplate,
|
||||
PaperTemplateProps,
|
||||
PaperTemplateTotalBorder,
|
||||
} from './PaperTemplate';
|
||||
import { Box, Group, Stack } from '@/components';
|
||||
import {
|
||||
DefaultPdfTemplateTerms,
|
||||
@@ -23,7 +27,7 @@ interface PaperTax {
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export interface InvoicePaperTemplateProps {
|
||||
export interface InvoicePaperTemplateProps extends PaperTemplateProps {
|
||||
primaryColor?: string;
|
||||
secondaryColor?: string;
|
||||
|
||||
@@ -177,9 +181,14 @@ export function InvoicePaperTemplate({
|
||||
statementLabel = 'Statement',
|
||||
showStatement = true,
|
||||
statement = DefaultPdfTemplateStatement,
|
||||
...props
|
||||
}: InvoicePaperTemplateProps) {
|
||||
return (
|
||||
<PaperTemplate primaryColor={primaryColor} secondaryColor={secondaryColor}>
|
||||
<PaperTemplate
|
||||
primaryColor={primaryColor}
|
||||
secondaryColor={secondaryColor}
|
||||
{...props}
|
||||
>
|
||||
<Stack spacing={24}>
|
||||
<Group align="start" spacing={10}>
|
||||
<Stack flex={1}>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import clsx from 'classnames';
|
||||
import { get, isFunction } from 'lodash';
|
||||
import { Box, Group, GroupProps } from '@/components';
|
||||
import { Box, BoxProps, Group, GroupProps } from '@/components';
|
||||
import styles from './InvoicePaperTemplate.module.scss';
|
||||
|
||||
export interface PaperTemplateProps {
|
||||
export interface PaperTemplateProps extends BoxProps {
|
||||
primaryColor?: string;
|
||||
secondaryColor?: string;
|
||||
children?: React.ReactNode;
|
||||
@@ -14,13 +14,13 @@ export function PaperTemplate({
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
children,
|
||||
...restProps
|
||||
}: PaperTemplateProps) {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Box {...restProps} className={clsx(styles.root, restProps?.className)}>
|
||||
<style>{`:root { --invoice-primary-color: ${primaryColor}; --invoice-secondary-color: ${secondaryColor}; }`}</style>
|
||||
|
||||
{children}
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,9 +118,9 @@ PaperTemplate.TotalLine = ({
|
||||
);
|
||||
};
|
||||
|
||||
PaperTemplate.MutedText = () => { };
|
||||
PaperTemplate.MutedText = () => {};
|
||||
|
||||
PaperTemplate.Text = () => { };
|
||||
PaperTemplate.Text = () => {};
|
||||
|
||||
PaperTemplate.AddressesGroup = (props: GroupProps) => {
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import * as R from 'ramda';
|
||||
import { Drawer, DrawerSuspense } from '@/components';
|
||||
import { InvoiceSendMailContent } from './InvoiceSendMailContent';
|
||||
import withDrawers from '@/containers/Drawer/withDrawers';
|
||||
import React from 'react';
|
||||
|
||||
const InvoiceSendMailContent = React.lazy(() =>
|
||||
import('./InvoiceSendMailContent').then((module) => ({
|
||||
default: module.InvoiceSendMailContent,
|
||||
})),
|
||||
);
|
||||
|
||||
interface InvoiceSendMailDrawerProps {
|
||||
name: string;
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
// @ts-nocheck
|
||||
import { useState } from 'react';
|
||||
import { Button, Intent, MenuItem } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { css } from '@emotion/css';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { unique, chain } from 'lodash';
|
||||
import {
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FMultiSelect,
|
||||
FTextArea,
|
||||
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})`,
|
||||
};
|
||||
import { SelectOptionProps } from '@blueprintjs-formik/select';
|
||||
|
||||
// Create new account renderer.
|
||||
const createNewItemRenderer = (query, active, handleClick) => {
|
||||
@@ -36,12 +33,47 @@ const createNewItemRenderer = (query, active, handleClick) => {
|
||||
const createNewItemFromQuery = (name) => ({ name });
|
||||
|
||||
export function InvoiceSendMailFields() {
|
||||
const allowCreate = true;
|
||||
// Maybe inject new item props to select component.
|
||||
const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
const [showCCField, setShowCCField] = useState<boolean>(false);
|
||||
const [showBccField, setShowBccField] = useState<boolean>(false);
|
||||
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
|
||||
const items = chain([...values?.to, ...values?.cc, ...values?.bcc])
|
||||
.filter((email) => !!email?.trim())
|
||||
.uniq()
|
||||
.map((email) => ({
|
||||
value: email,
|
||||
text: email,
|
||||
}))
|
||||
.value();
|
||||
|
||||
const handleClickCcBtn = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
setShowCCField(true);
|
||||
};
|
||||
|
||||
const handleClickBccBtn = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
setShowBccField(true);
|
||||
};
|
||||
|
||||
const handleCreateToItemSelect = (value: SelectOptionProps) => {
|
||||
const _value = [...values?.to, value?.name];
|
||||
setFieldValue('to', _value);
|
||||
};
|
||||
|
||||
const handleCreateCcItemSelect = (value: SelectOptionProps) => {
|
||||
const _value = [...values?.cc, value?.name];
|
||||
setFieldValue('cc', _value);
|
||||
};
|
||||
const handleCreateBccItemSelect = (value: SelectOptionProps) => {
|
||||
const _value = [...values?.bcc, value?.name];
|
||||
setFieldValue('bcc', _value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -51,54 +83,109 @@ export function InvoiceSendMailFields() {
|
||||
spacing={0}
|
||||
borderRight="1px solid #dcdcdd"
|
||||
>
|
||||
<Stack overflow="auto" flex="1" p={'30px'}>
|
||||
<FFormGroup label={'to'} name={'To'}>
|
||||
<Stack spacing={0}>
|
||||
<Stack spacing={0} overflow="auto" flex="1" p={'30px'} className={css`
|
||||
|
||||
`}>
|
||||
<FFormGroup label={'To'} name={'to'}>
|
||||
<Stack spacing={0} className={css`
|
||||
> :not(:first-of-type) .bp4-input{
|
||||
border-top-color: transparent;
|
||||
border-top-right-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
}
|
||||
> :not(:last-of-type) .bp4-input {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
`}>
|
||||
<FMultiSelect
|
||||
items={[]}
|
||||
items={items}
|
||||
name={'to'}
|
||||
placeholder={''}
|
||||
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
|
||||
spacing={10}
|
||||
paddingRight={12}
|
||||
fontWeight={500}
|
||||
color={'#000'}
|
||||
>
|
||||
<x.a
|
||||
href="#"
|
||||
onClick={handleClickCcBtn}
|
||||
color="#404854"
|
||||
fontSize={'12px'}
|
||||
className={css`
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
`}
|
||||
>
|
||||
CC
|
||||
</x.a>
|
||||
|
||||
<x.a
|
||||
href="#"
|
||||
onClick={handleClickBccBtn}
|
||||
color="#404854"
|
||||
fontSize={'12px'}
|
||||
className={css`
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
`}
|
||||
>
|
||||
BCC
|
||||
</x.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}
|
||||
createNewItemRenderer={createNewItemRenderer}
|
||||
createNewItemFromQuery={createNewItemFromQuery}
|
||||
onCreateItemSelect={handleCreateToItemSelect}
|
||||
resetOnQuery
|
||||
resetOnSelect
|
||||
fill
|
||||
/>
|
||||
{showCCField && (
|
||||
<FMultiSelect
|
||||
items={items}
|
||||
name={'cc'}
|
||||
placeholder={''}
|
||||
popoverProps={{ minimal: true, fill: true }}
|
||||
tagInputProps={{
|
||||
tagProps: { round: true, minimal: true, large: true },
|
||||
large: true,
|
||||
}}
|
||||
createNewItemRenderer={createNewItemRenderer}
|
||||
createNewItemFromQuery={createNewItemFromQuery}
|
||||
onCreateItemSelect={handleCreateCcItemSelect}
|
||||
resetOnQuery
|
||||
resetOnSelect
|
||||
fill
|
||||
/>
|
||||
)}
|
||||
{showBccField && (
|
||||
<FMultiSelect
|
||||
items={items}
|
||||
name={'bcc'}
|
||||
placeholder={''}
|
||||
popoverProps={{ minimal: true, fill: true }}
|
||||
tagInputProps={{
|
||||
tagProps: { round: true, minimal: true, large: true },
|
||||
large: true,
|
||||
}}
|
||||
createNewItemRenderer={createNewItemRenderer}
|
||||
createNewItemFromQuery={createNewItemFromQuery}
|
||||
onCreateItemSelect={handleCreateBccItemSelect}
|
||||
resetOnQuery
|
||||
resetOnSelect
|
||||
fill
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</FFormGroup>
|
||||
|
||||
@@ -107,7 +194,15 @@ export function InvoiceSendMailFields() {
|
||||
</FFormGroup>
|
||||
|
||||
<FFormGroup label={'Message'} name={'message'}>
|
||||
<FInputGroup name={'message'} large />
|
||||
<FTextArea
|
||||
name={'message'}
|
||||
large
|
||||
fill
|
||||
className={css`
|
||||
resize: vertical;
|
||||
min-height: 200px;
|
||||
`}
|
||||
/>
|
||||
</FFormGroup>
|
||||
</Stack>
|
||||
|
||||
|
||||
@@ -3,11 +3,22 @@ import { Form, Formik, FormikHelpers } from 'formik';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
const initialValues = {
|
||||
subject: '',
|
||||
message: '',
|
||||
to: [],
|
||||
subject: 'invoice INV-0002 for AED 0.00',
|
||||
message: `Hi Ahmed,
|
||||
|
||||
Here’s invoice INV-0002 for AED 0.00
|
||||
|
||||
The amount outstanding of AED $100,00 is due on 2 October 2024
|
||||
|
||||
View your bill online From your online you can print a PDF or pay your outstanding bills,
|
||||
|
||||
If you have any questions, please let us know,
|
||||
|
||||
Thanks,
|
||||
Mohamed`,
|
||||
to: ['a.bouhuolia@gmail.com'],
|
||||
cc: [],
|
||||
bcc: []
|
||||
bcc: [],
|
||||
};
|
||||
interface InvoiceSendMailFormValues {
|
||||
subject: string;
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import { Button, Classes } from "@blueprintjs/core";
|
||||
import { Group, Icon } from "@/components";
|
||||
import { useDrawerContext } from "@/components/Drawer/DrawerProvider";
|
||||
import { useDrawerActions } from "@/hooks/state";
|
||||
import { Button, Classes } from '@blueprintjs/core';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { Group, Icon } from '@/components';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useDrawerActions } from '@/hooks/state';
|
||||
|
||||
interface ElementCustomizeHeaderProps {
|
||||
label?: string;
|
||||
children?: React.ReactNode;
|
||||
closeButton?: boolean;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export function InvoiceSendMailHeader({
|
||||
label,
|
||||
closeButton = true,
|
||||
onClose,
|
||||
children,
|
||||
}: ElementCustomizeHeaderProps) {
|
||||
const { name } = useDrawerContext();
|
||||
const { closeDrawer } = useDrawerActions();
|
||||
@@ -25,7 +22,7 @@ export function InvoiceSendMailHeader({
|
||||
return (
|
||||
<Group
|
||||
p={'10px'}
|
||||
pl={'15px'}
|
||||
pl={'30px'}
|
||||
bg="white"
|
||||
alignItems={'center'}
|
||||
boxShadow={'0 1px 0 rgba(17, 20, 24, .15)'}
|
||||
@@ -33,9 +30,9 @@ export function InvoiceSendMailHeader({
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
{label && (
|
||||
<h1 style={{ margin: 0, fontSize: 20, fontWeight: 500, color: '#666' }}>
|
||||
<x.h1 margin={0} fontSize={20} fontWeight={500} color={'#666'}>
|
||||
{label}
|
||||
</h1>
|
||||
</x.h1>
|
||||
)}
|
||||
{closeButton && (
|
||||
<Button
|
||||
|
||||
@@ -101,7 +101,7 @@ function InvoicesDataTable({
|
||||
|
||||
// Handle send mail invoice.
|
||||
const handleSendMailInvoice = ({ id }) => {
|
||||
openDialog(DialogsName.InvoiceMail, { invoiceId: id });
|
||||
openDrawer(DRAWERS.INVOICE_SEND_MAIL, { invoiceId: id });
|
||||
};
|
||||
|
||||
// Handle cell click.
|
||||
|
||||
Reference in New Issue
Block a user