mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
feat: element customize component
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
|
||||
.field{
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.colorPicker{
|
||||
background-color: rgb(103, 114, 229);
|
||||
border-radius: 3px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import clsx from 'classnames';
|
||||
import {
|
||||
IInputGroupProps,
|
||||
InputGroup,
|
||||
IPopoverProps,
|
||||
Popover,
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { HexColorPicker } from 'react-colorful';
|
||||
import { useUncontrolled } from '@/hooks/useUncontrolled';
|
||||
import { Box, BoxProps } from '@/components';
|
||||
import styles from './ColorField.module.scss';
|
||||
|
||||
export interface ColorFieldProps {
|
||||
value?: string;
|
||||
initialValue?: string;
|
||||
onChange?: (value: string) => void;
|
||||
popoverProps?: Partial<IPopoverProps>;
|
||||
inputProps?: Partial<IInputGroupProps>;
|
||||
pickerProps?: Partial<BoxProps>;
|
||||
pickerWrapProps?: Partial<BoxProps>;
|
||||
}
|
||||
|
||||
export function ColorField({
|
||||
value,
|
||||
initialValue,
|
||||
onChange,
|
||||
popoverProps,
|
||||
inputProps,
|
||||
pickerWrapProps,
|
||||
pickerProps,
|
||||
}: ColorFieldProps) {
|
||||
const [_value, handleChange] = useUncontrolled({
|
||||
value,
|
||||
initialValue,
|
||||
onChange,
|
||||
finalValue: '',
|
||||
});
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
|
||||
const handleClose = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={<HexColorPicker color={_value} onChange={handleChange} />}
|
||||
position={Position.BOTTOM}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
modifiers={{
|
||||
offset: { offset: '0, 4' },
|
||||
}}
|
||||
onClose={handleClose}
|
||||
isOpen={isOpen}
|
||||
minimal
|
||||
{...popoverProps}
|
||||
>
|
||||
<InputGroup
|
||||
value={_value}
|
||||
leftElement={
|
||||
<Box
|
||||
{...pickerWrapProps}
|
||||
style={{ padding: 8, ...pickerWrapProps?.style }}
|
||||
>
|
||||
<Box
|
||||
onClick={() => setIsOpen((oldValue) => !oldValue)}
|
||||
style={{ backgroundColor: _value }}
|
||||
className={clsx(styles.colorPicker, pickerProps?.className)}
|
||||
{...pickerProps}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
{...inputProps}
|
||||
className={clsx(styles.field, inputProps?.className)}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
|
||||
interface CreditCardIconProps extends SVGProps<SVGSVGElement> {
|
||||
}
|
||||
|
||||
|
||||
export function CreditCardIcon(props: CreditCardIconProps) {
|
||||
return (
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 16 16"
|
||||
enable-background="new 0 0 16 16"
|
||||
{...props}
|
||||
>
|
||||
<g id="credit_card_2_">
|
||||
<g>
|
||||
<path
|
||||
d="M14.99,2.95h-14c-0.55,0-1,0.45-1,1v1h16v-1C15.99,3.4,15.54,2.95,14.99,2.95z M-0.01,12.95c0,0.55,0.45,1,1,1h14
|
||||
c0.55,0,1-0.45,1-1v-6h-16C-0.01,6.95-0.01,12.95-0.01,12.95z M5.49,10.95h5c0.28,0,0.5,0.22,0.5,0.5s-0.22,0.5-0.5,0.5h-5
|
||||
c-0.28,0-0.5-0.22-0.5-0.5S5.22,10.95,5.49,10.95z M2.49,10.95h1c0.28,0,0.5,0.22,0.5,0.5s-0.22,0.5-0.5,0.5h-1
|
||||
c-0.28,0-0.5-0.22-0.5-0.5S2.22,10.95,2.49,10.95z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
import React from 'react';
|
||||
import { getIn, FieldConfig, FieldProps } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { Field } from '@blueprintjs-formik/core';
|
||||
import { ColorField, ColorFieldProps } from './ColorField';
|
||||
|
||||
interface ColorFieldInputGroupProps
|
||||
extends Omit<FieldConfig, 'children' | 'component' | 'as' | 'value'>,
|
||||
ColorFieldProps {}
|
||||
|
||||
export interface ColorFieldToInputProps
|
||||
extends Omit<FieldProps, 'onChange'>,
|
||||
ColorFieldProps {}
|
||||
|
||||
/**
|
||||
* Transforms field props to input group props for ColorField.
|
||||
* @param {ColorFieldToInputProps}
|
||||
* @returns {ColorFieldProps}
|
||||
*/
|
||||
function fieldToColorFieldInputGroup({
|
||||
field: { onBlur: onFieldBlur, onChange: onFieldChange, value, ...field },
|
||||
form: { touched, errors, setFieldValue },
|
||||
onChange,
|
||||
...props
|
||||
}: ColorFieldToInputProps): ColorFieldProps {
|
||||
const fieldError = getIn(errors, field.name);
|
||||
const showError = getIn(touched, field.name) && !!fieldError;
|
||||
|
||||
return {
|
||||
inputProps: {
|
||||
intent: showError ? Intent.DANGER : Intent.NONE,
|
||||
},
|
||||
value,
|
||||
onChange:
|
||||
onChange ??
|
||||
function (value: string) {
|
||||
setFieldValue(field.name, value);
|
||||
},
|
||||
...field,
|
||||
...props,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms field props to input group props for ColorField.
|
||||
* @param {ColorFieldToInputProps} props -
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
function ColorFieldToInputGroup({
|
||||
...props
|
||||
}: ColorFieldToInputProps): JSX.Element {
|
||||
return <ColorField {...fieldToColorFieldInputGroup(props)} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input group Blueprint component binded with Formik for ColorField.
|
||||
* @param {ColorFieldInputGroupProps}
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
export function FColorInput({
|
||||
...props
|
||||
}: ColorFieldInputGroupProps): JSX.Element {
|
||||
return <Field {...props} component={ColorFieldToInputGroup} />;
|
||||
}
|
||||
@@ -1,74 +1,65 @@
|
||||
import React from 'react';
|
||||
import { Box, Group } from '@/components';
|
||||
import { InvoiceCustomizeProvider } from './InvoiceCustomizeProvider';
|
||||
import {
|
||||
InvoiceCustomizeForm,
|
||||
InvoiceCustomizeFormProps,
|
||||
} from './InvoiceCustomizerForm';
|
||||
import { InvoiceCustomizeTabsControllerProvider } from './InvoiceCustomizeTabsController';
|
||||
import { InvoiceCustomizeFields } from './InvoiceCustomizeFields';
|
||||
import { InvoiceCustomizePreview } from './InvoiceCustomizePreview';
|
||||
import { extractChildren } from '@/utils/extract-children';
|
||||
import { Box } from '@/components';
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { InvoicePaperTemplate } from './InvoicePaperTemplate';
|
||||
import { ElementCustomize } from '../../../ElementCustomize/ElementCustomize';
|
||||
import { InvoiceCustomizeGeneralField } from './InvoiceCustomizeGeneralFields';
|
||||
import { InvoiceCustomizeContentFields } from './InvoiceCutomizeContentFields';
|
||||
|
||||
export interface InvoiceCustomizeProps<T> extends InvoiceCustomizeFormProps<T> {
|
||||
children?: React.ReactNode;
|
||||
interface InvoiceCustomizeValues {
|
||||
invoiceNumber?: string;
|
||||
invoiceNumberLabel?: string;
|
||||
|
||||
dateIssue?: string;
|
||||
dateIssueLabel?: string;
|
||||
|
||||
dueDate?: string;
|
||||
dueDateLabel?: string;
|
||||
|
||||
companyName?: string;
|
||||
|
||||
bigtitle?: string;
|
||||
|
||||
itemRateLabel?: string;
|
||||
itemQuantityLabel?: string;
|
||||
itemTotalLabel?: string;
|
||||
|
||||
// Totals
|
||||
showDueAmount?: boolean;
|
||||
showDiscount?: boolean;
|
||||
showPaymentMade?: boolean;
|
||||
showTaxes?: boolean;
|
||||
showSubtotal?: boolean;
|
||||
showTotal?: boolean;
|
||||
showBalanceDue?: boolean;
|
||||
|
||||
paymentMadeLabel?: string;
|
||||
discountLabel?: string;
|
||||
subtotalLabel?: string;
|
||||
totalLabel?: string;
|
||||
balanceDueLabel?: string;
|
||||
}
|
||||
|
||||
export function InvoiceCustomize<T>({
|
||||
initialValues,
|
||||
validationSchema,
|
||||
onSubmit,
|
||||
children,
|
||||
}: InvoiceCustomizeProps<T>) {
|
||||
const PaperTemplate = React.useMemo(
|
||||
() => extractChildren(children, InvoiceCustomize.PaperTemplate),
|
||||
[children],
|
||||
);
|
||||
const CustomizeTabs = React.useMemo(
|
||||
() => extractChildren(children, InvoiceCustomize.FieldsTab),
|
||||
[children],
|
||||
);
|
||||
|
||||
const value = { PaperTemplate, CustomizeTabs };
|
||||
|
||||
export default function InvoiceCustomizeContent() {
|
||||
return (
|
||||
<InvoiceCustomizeForm
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<InvoiceCustomizeTabsControllerProvider>
|
||||
<InvoiceCustomizeProvider value={value}>
|
||||
<Group spacing={0} align="stretch">
|
||||
<InvoiceCustomizeFields />
|
||||
<InvoiceCustomizePreview />
|
||||
</Group>
|
||||
</InvoiceCustomizeProvider>
|
||||
</InvoiceCustomizeTabsControllerProvider>
|
||||
</InvoiceCustomizeForm>
|
||||
<Box className={Classes.DRAWER_BODY}>
|
||||
<ElementCustomize<InvoiceCustomizeValues>>
|
||||
<ElementCustomize.PaperTemplate>
|
||||
<InvoicePaperTemplate />
|
||||
</ElementCustomize.PaperTemplate>
|
||||
|
||||
<ElementCustomize.FieldsTab id={'general'} label={'General'}>
|
||||
<InvoiceCustomizeGeneralField />
|
||||
</ElementCustomize.FieldsTab>
|
||||
|
||||
<ElementCustomize.FieldsTab id={'content'} label={'Content'}>
|
||||
<InvoiceCustomizeContentFields />
|
||||
</ElementCustomize.FieldsTab>
|
||||
|
||||
<ElementCustomize.FieldsTab id={'totals'} label={'Totals'}>
|
||||
asdfasdfdsaf #3
|
||||
</ElementCustomize.FieldsTab>
|
||||
</ElementCustomize>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export interface InvoiceCustomizePaperTemplateProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
InvoiceCustomize.PaperTemplate = ({
|
||||
children,
|
||||
}: InvoiceCustomizePaperTemplateProps) => {
|
||||
return <Box>{children}</Box>;
|
||||
};
|
||||
|
||||
export interface InvoiceCustomizeContentProps {
|
||||
id: string;
|
||||
label: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
InvoiceCustomize.FieldsTab = ({
|
||||
id,
|
||||
label,
|
||||
children,
|
||||
}: InvoiceCustomizeContentProps) => {
|
||||
return <Box>{children}</Box>;
|
||||
};
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@/components';
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { InvoicePaperTemplate } from './InvoicePaperTemplate';
|
||||
import { InvoiceCustomize } from './InvoiceCustomize';
|
||||
import { InvoiceCustomizeGeneralField } from './InvoiceCustomizeGeneralFields';
|
||||
import { InvoiceCustomizeContentFields } from './InvoiceCutomizeContentFields';
|
||||
|
||||
interface InvoiceCustomizeValues {
|
||||
invoiceNumber?: string;
|
||||
invoiceNumberLabel?: string;
|
||||
|
||||
dateIssue?: string;
|
||||
dateIssueLabel?: string;
|
||||
|
||||
dueDate?: string;
|
||||
dueDateLabel?: string;
|
||||
|
||||
companyName?: string;
|
||||
|
||||
bigtitle?: string;
|
||||
|
||||
itemRateLabel?: string;
|
||||
itemQuantityLabel?: string;
|
||||
itemTotalLabel?: string;
|
||||
|
||||
// Totals
|
||||
showDueAmount?: boolean;
|
||||
showDiscount?: boolean;
|
||||
showPaymentMade?: boolean;
|
||||
showTaxes?: boolean;
|
||||
showSubtotal?: boolean;
|
||||
showTotal?: boolean;
|
||||
showBalanceDue?: boolean;
|
||||
|
||||
paymentMadeLabel?: string;
|
||||
discountLabel?: string;
|
||||
subtotalLabel?: string;
|
||||
totalLabel?: string;
|
||||
balanceDueLabel?: string;
|
||||
}
|
||||
|
||||
export default function InvoiceCustomizeContent() {
|
||||
return (
|
||||
<Box className={Classes.DRAWER_BODY}>
|
||||
<InvoiceCustomize<InvoiceCustomizeValues>>
|
||||
<InvoiceCustomize.PaperTemplate>
|
||||
<InvoicePaperTemplate />
|
||||
</InvoiceCustomize.PaperTemplate>
|
||||
|
||||
<InvoiceCustomize.FieldsTab id={'general'} label={'General'}>
|
||||
<InvoiceCustomizeGeneralField />
|
||||
</InvoiceCustomize.FieldsTab>
|
||||
|
||||
<InvoiceCustomize.FieldsTab id={'content'} label={'Content'}>
|
||||
<InvoiceCustomizeContentFields />
|
||||
</InvoiceCustomize.FieldsTab>
|
||||
|
||||
<InvoiceCustomize.FieldsTab id={'totals'} label={'Totals'}>
|
||||
asdfasdfdsaf #3
|
||||
</InvoiceCustomize.FieldsTab>
|
||||
</InvoiceCustomize>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import * as R from 'ramda';
|
||||
import { Drawer, DrawerSuspense } from '@/components';
|
||||
import withDrawers from '@/containers/Drawer/withDrawers';
|
||||
|
||||
const InvoiceCustomizeContent = React.lazy(
|
||||
() => import('./InvoiceCustomizeContent'),
|
||||
const InvoiceCustomize = React.lazy(
|
||||
() => import('./InvoiceCustomize'),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -21,7 +21,7 @@ function InvoiceCustomizeDrawerRoot({
|
||||
return (
|
||||
<Drawer isOpen={isOpen} name={name} size={'100%'}>
|
||||
<DrawerSuspense>
|
||||
<InvoiceCustomizeContent />
|
||||
<InvoiceCustomize />
|
||||
</DrawerSuspense>
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { Group, Stack } from '@/components';
|
||||
import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader';
|
||||
import { InvoiceCustomizeTabs } from './InvoiceCustomizeTabs';
|
||||
import { useInvoiceCustomizeTabsController } from './InvoiceCustomizeTabsController';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useInvoiceCustomizeContext } from './InvoiceCustomizeProvider';
|
||||
import styles from './InvoiceCustomizeFields.module.scss';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
|
||||
export function InvoiceCustomizeFields() {
|
||||
return (
|
||||
<Group spacing={0} align={'stretch'} className={styles.root}>
|
||||
<InvoiceCustomizeTabs />
|
||||
<InvoiceCustomizeFieldsMain />
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeFieldsMain() {
|
||||
const { currentTabId } = useInvoiceCustomizeTabsController();
|
||||
const { CustomizeTabs } = useInvoiceCustomizeContext();
|
||||
|
||||
const CustomizeTabPanel = React.useMemo(
|
||||
() =>
|
||||
React.Children.map(CustomizeTabs, (tab) => {
|
||||
return tab.props.id === currentTabId ? tab : null;
|
||||
}).filter(Boolean),
|
||||
[CustomizeTabs, currentTabId],
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack spacing={0} className={styles.mainFields}>
|
||||
<InvoiceCustomizeHeader label={'Customize'} />
|
||||
|
||||
<Stack spacing={0} style={{ flex: '1 1 auto', overflow: 'auto' }}>
|
||||
{CustomizeTabPanel}
|
||||
<InvoiceCustomizeFooterActions />
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function InvoiceCustomizeFooterActionsRoot({ closeDrawer }) {
|
||||
const { name } = useDrawerContext();
|
||||
const { submitForm } = useFormikContext();
|
||||
|
||||
const handleSubmitBtnClick = () => {
|
||||
submitForm();
|
||||
};
|
||||
const handleCancelBtnClick = () => {
|
||||
closeDrawer(name);
|
||||
};
|
||||
|
||||
return (
|
||||
<Group spacing={10} className={styles.footerActions}>
|
||||
<Button
|
||||
onClick={handleSubmitBtnClick}
|
||||
intent={Intent.PRIMARY}
|
||||
style={{ minWidth: 75 }}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
const InvoiceCustomizeFooterActions = R.compose(withDrawerActions)(
|
||||
InvoiceCustomizeFooterActionsRoot,
|
||||
);
|
||||
@@ -1,9 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import { Box, FFormGroup, FSwitch, Group, Stack } from '@/components';
|
||||
import { FColorInput } from './FColorField';
|
||||
import styles from './InvoiceCustomizeFields.module.scss';
|
||||
import { Classes, Text } from '@blueprintjs/core';
|
||||
import { CreditCardIcon } from './CreditCardIcon';
|
||||
import { FFormGroup, FSwitch, Group, Stack } from '@/components';
|
||||
import { FColorInput } from '@/components/Forms/FColorInput';
|
||||
import { CreditCardIcon } from '@/icons/CreditCardIcon';
|
||||
import styles from './InvoiceCustomizeFields.module.scss';
|
||||
|
||||
export function InvoiceCustomizeGeneralField() {
|
||||
return (
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
.root {
|
||||
align-items: center;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 1px 0 rgba(17, 20, 24, .15);
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
min-height: 55px;
|
||||
padding: 5px 5px 5px 20px;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.title{
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Group, Icon } from '@/components';
|
||||
import { Button, Classes } from '@blueprintjs/core';
|
||||
import styles from './InvoiceCustomizeHeader.module.scss';
|
||||
|
||||
interface InvoiceCustomizeHeaderProps {
|
||||
label?: string;
|
||||
children?: React.ReactNode;
|
||||
closeButton?: boolean;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeHeader({
|
||||
label,
|
||||
closeButton,
|
||||
onClose,
|
||||
children,
|
||||
}: InvoiceCustomizeHeaderProps) {
|
||||
const handleClose = () => {
|
||||
onClose && onClose();
|
||||
};
|
||||
return (
|
||||
<Group className={styles.root}>
|
||||
{label && <h1 className={styles.title}>{label}</h1>}
|
||||
{closeButton && (
|
||||
<Button
|
||||
aria-label="Close"
|
||||
className={Classes.DIALOG_CLOSE_BUTTON}
|
||||
icon={<Icon icon={'smallCross'} color={'#000'} />}
|
||||
minimal={true}
|
||||
onClick={handleClose}
|
||||
style={{ marginLeft: 'auto' }}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import * as R from 'ramda';
|
||||
import { Stack } from '@/components';
|
||||
import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader';
|
||||
import { InvoiceCustomizePreviewContent } from './InvoiceCustomizePreviewContent';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
|
||||
function InvoiceCustomizePreviewRoot({ closeDrawer }) {
|
||||
const { name } = useDrawerContext();
|
||||
|
||||
const handleCloseBtnClick = () => {
|
||||
closeDrawer(name);
|
||||
};
|
||||
return (
|
||||
<Stack spacing={0} style={{ borderLeft: '1px solid #D9D9D9', height: '100vh', flex: '1 1' }}>
|
||||
<InvoiceCustomizeHeader
|
||||
label={'Preview'}
|
||||
closeButton
|
||||
onClose={handleCloseBtnClick}
|
||||
/>
|
||||
<InvoiceCustomizePreviewContent />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export const InvoiceCustomizePreview = R.compose(withDrawerActions)(
|
||||
InvoiceCustomizePreviewRoot,
|
||||
);
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Box } from '@/components';
|
||||
import { useInvoiceCustomizeContext } from './InvoiceCustomizeProvider';
|
||||
|
||||
export function InvoiceCustomizePreviewContent() {
|
||||
const { PaperTemplate } = useInvoiceCustomizeContext();
|
||||
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
padding: '28px 24px 40px',
|
||||
backgroundColor: '#F5F5F5',
|
||||
overflow: 'auto',
|
||||
flex: '1',
|
||||
}}
|
||||
>
|
||||
{PaperTemplate}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
|
||||
interface InvoiceCustomizeValue {
|
||||
PaperTemplate?: React.ReactNode;
|
||||
CustomizeTabs: React.ReactNode;
|
||||
}
|
||||
|
||||
const InvoiceCustomizeContext = createContext<InvoiceCustomizeValue>(
|
||||
{} as InvoiceCustomizeValue,
|
||||
);
|
||||
|
||||
export const InvoiceCustomizeProvider: React.FC<{
|
||||
value: InvoiceCustomizeValue;
|
||||
children: React.ReactNode;
|
||||
}> = ({ value, children }) => {
|
||||
return (
|
||||
<InvoiceCustomizeContext.Provider value={{ ...value }}>
|
||||
{children}
|
||||
</InvoiceCustomizeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useInvoiceCustomizeContext = (): InvoiceCustomizeValue => {
|
||||
const context = useContext<InvoiceCustomizeValue>(InvoiceCustomizeContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useInvoiceCustomize must be used within an InvoiceCustomizeProvider',
|
||||
);
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
.root {
|
||||
flex: 1;
|
||||
min-width: 165px;
|
||||
max-width: 165px;
|
||||
}
|
||||
|
||||
.content{
|
||||
padding: 5px;
|
||||
flex: 1;
|
||||
border-right: 1px solid #E1E1E1;
|
||||
}
|
||||
|
||||
.tabsList{
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
|
||||
:global .bp4-tab-list{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Box, Stack } from '@/components';
|
||||
import { Tab, Tabs } from '@blueprintjs/core';
|
||||
import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader';
|
||||
import {
|
||||
InvoiceCustomizeTabsEnum,
|
||||
useInvoiceCustomizeTabsController,
|
||||
} from './InvoiceCustomizeTabsController';
|
||||
import styles from './InvoiceCustomizeTabs.module.scss';
|
||||
import { useInvoiceCustomizeContext } from './InvoiceCustomizeProvider';
|
||||
import React from 'react';
|
||||
|
||||
export function InvoiceCustomizeTabs() {
|
||||
const { setCurrentTabId } = useInvoiceCustomizeTabsController();
|
||||
|
||||
const { CustomizeTabs } = useInvoiceCustomizeContext();
|
||||
|
||||
const tabItems = React.Children.map(CustomizeTabs, (node) => ({
|
||||
...(React.isValidElement(node) ? node.props : {}),
|
||||
}));
|
||||
const handleChange = (value: InvoiceCustomizeTabsEnum) => {
|
||||
setCurrentTabId(value);
|
||||
};
|
||||
return (
|
||||
<Stack spacing={0} className={styles.root}>
|
||||
<InvoiceCustomizeHeader label={''} />
|
||||
|
||||
<Box className={styles.content}>
|
||||
<Tabs
|
||||
vertical
|
||||
fill
|
||||
large
|
||||
onChange={handleChange}
|
||||
className={styles.tabsList}
|
||||
>
|
||||
{tabItems?.map(({ id, label }: { id: string; label: string }) => (
|
||||
<Tab id={id} key={id} title={label} />
|
||||
))}
|
||||
</Tabs>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
|
||||
export enum InvoiceCustomizeTabsEnum {
|
||||
General = 'general',
|
||||
Items = 'items',
|
||||
Totals = 'totals'
|
||||
}
|
||||
|
||||
const DEFAULT_TAB_ID = InvoiceCustomizeTabsEnum.General;
|
||||
|
||||
interface InvoiceCustomizeTabsControllerValue {
|
||||
currentTabId: InvoiceCustomizeTabsEnum;
|
||||
setCurrentTabId: React.Dispatch<
|
||||
React.SetStateAction<InvoiceCustomizeTabsEnum>
|
||||
>;
|
||||
}
|
||||
|
||||
const InvoiceCustomizeTabsController = createContext(
|
||||
{} as InvoiceCustomizeTabsControllerValue,
|
||||
);
|
||||
|
||||
export const useInvoiceCustomizeTabsController = () => {
|
||||
return useContext(InvoiceCustomizeTabsController);
|
||||
};
|
||||
|
||||
interface InvoiceCustomizeTabsControllerProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const InvoiceCustomizeTabsControllerProvider = ({
|
||||
children,
|
||||
}: InvoiceCustomizeTabsControllerProps) => {
|
||||
const [currentTabId, setCurrentTabId] =
|
||||
useState<InvoiceCustomizeTabsEnum>(DEFAULT_TAB_ID);
|
||||
|
||||
const value = {
|
||||
currentTabId,
|
||||
setCurrentTabId,
|
||||
};
|
||||
|
||||
return (
|
||||
<InvoiceCustomizeTabsController.Provider value={value}>
|
||||
{children}
|
||||
</InvoiceCustomizeTabsController.Provider>
|
||||
);
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Formik, Form, FormikHelpers } from 'formik';
|
||||
|
||||
export interface InvoiceCustomizeFormProps<T> {
|
||||
initialValues?: T;
|
||||
validationSchema?: any;
|
||||
onSubmit?: (values: T, formikHelpers: FormikHelpers<T>) => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeForm<T>({
|
||||
initialValues,
|
||||
validationSchema,
|
||||
onSubmit,
|
||||
children,
|
||||
}: InvoiceCustomizeFormProps<T>) {
|
||||
return (
|
||||
<Formik<T>
|
||||
initialValues={{ ...initialValues }}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={(value, helpers) => onSubmit && onSubmit(value, helpers)}
|
||||
>
|
||||
<Form>{children}</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FInputGroup, FSwitch, Group, Stack } from '@/components';
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { FInputGroup, FSwitch, Group, Stack } from '@/components';
|
||||
|
||||
const items = [
|
||||
{ key: 'dueAmount', label: 'Due Amount' },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from 'classnames';
|
||||
import styles from './PaperTemplate.module.scss';
|
||||
import styles from './InvoicePaperTemplate.module.scss';
|
||||
|
||||
interface PaperTemplateProps {
|
||||
invoiceNumber?: string;
|
||||
|
||||
Reference in New Issue
Block a user