mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
feat: element customize component
This commit is contained in:
@@ -11,9 +11,9 @@ import {
|
||||
import { HexColorPicker } from 'react-colorful';
|
||||
import { useUncontrolled } from '@/hooks/useUncontrolled';
|
||||
import { Box, BoxProps } from '@/components';
|
||||
import styles from './ColorField.module.scss';
|
||||
import styles from './ColorInput.module.scss';
|
||||
|
||||
export interface ColorFieldProps {
|
||||
export interface ColorInputProps {
|
||||
value?: string;
|
||||
initialValue?: string;
|
||||
onChange?: (value: string) => void;
|
||||
@@ -23,7 +23,7 @@ export interface ColorFieldProps {
|
||||
pickerWrapProps?: Partial<BoxProps>;
|
||||
}
|
||||
|
||||
export function ColorField({
|
||||
export function ColorInput({
|
||||
value,
|
||||
initialValue,
|
||||
onChange,
|
||||
@@ -31,7 +31,7 @@ export function ColorField({
|
||||
inputProps,
|
||||
pickerWrapProps,
|
||||
pickerProps,
|
||||
}: ColorFieldProps) {
|
||||
}: ColorInputProps) {
|
||||
const [_value, handleChange] = useUncontrolled({
|
||||
value,
|
||||
initialValue,
|
||||
@@ -2,27 +2,27 @@ 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';
|
||||
import { ColorInput, ColorInputProps } from './ColorInput';
|
||||
|
||||
interface ColorFieldInputGroupProps
|
||||
interface ColorInputInputGroupProps
|
||||
extends Omit<FieldConfig, 'children' | 'component' | 'as' | 'value'>,
|
||||
ColorFieldProps {}
|
||||
ColorInputProps {}
|
||||
|
||||
export interface ColorFieldToInputProps
|
||||
export interface ColorInputToInputProps
|
||||
extends Omit<FieldProps, 'onChange'>,
|
||||
ColorFieldProps {}
|
||||
ColorInputProps {}
|
||||
|
||||
/**
|
||||
* Transforms field props to input group props for ColorField.
|
||||
* @param {ColorFieldToInputProps}
|
||||
* @returns {ColorFieldProps}
|
||||
* Transforms field props to input group props for ColorInput.
|
||||
* @param {ColorInputToInputProps}
|
||||
* @returns {ColorInputProps}
|
||||
*/
|
||||
function fieldToColorFieldInputGroup({
|
||||
function fieldToColorInputInputGroup({
|
||||
field: { onBlur: onFieldBlur, onChange: onFieldChange, value, ...field },
|
||||
form: { touched, errors, setFieldValue },
|
||||
onChange,
|
||||
...props
|
||||
}: ColorFieldToInputProps): ColorFieldProps {
|
||||
}: ColorInputToInputProps): ColorInputProps {
|
||||
const fieldError = getIn(errors, field.name);
|
||||
const showError = getIn(touched, field.name) && !!fieldError;
|
||||
|
||||
@@ -42,23 +42,23 @@ function fieldToColorFieldInputGroup({
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms field props to input group props for ColorField.
|
||||
* @param {ColorFieldToInputProps} props -
|
||||
* Transforms field props to input group props for ColorInput.
|
||||
* @param {ColorInputToInputProps} props -
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
function ColorFieldToInputGroup({
|
||||
function ColorInputToInputGroup({
|
||||
...props
|
||||
}: ColorFieldToInputProps): JSX.Element {
|
||||
return <ColorField {...fieldToColorFieldInputGroup(props)} />;
|
||||
}: ColorInputToInputProps): JSX.Element {
|
||||
return <ColorInput {...fieldToColorInputInputGroup(props)} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input group Blueprint component binded with Formik for ColorField.
|
||||
* @param {ColorFieldInputGroupProps}
|
||||
* Input group Blueprint component binded with Formik for ColorInput.
|
||||
* @param {ColorInputInputGroupProps}
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
export function FColorInput({
|
||||
...props
|
||||
}: ColorFieldInputGroupProps): JSX.Element {
|
||||
return <Field {...props} component={ColorFieldToInputGroup} />;
|
||||
}: ColorInputInputGroupProps): JSX.Element {
|
||||
return <Field {...props} component={ColorInputToInputGroup} />;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
.root {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.mainFields{
|
||||
width: 400px;
|
||||
height: 100vh;
|
||||
}
|
||||
.fieldGroup {
|
||||
|
||||
:global .bp4-form-content{
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.footerActions{
|
||||
padding: 10px 16px;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
flex-flow: row-reverse;
|
||||
}
|
||||
|
||||
.showCompanyLogoField:global(.bp4-large){
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import React from 'react';
|
||||
import { Box, Group } from '@/components';
|
||||
import { ElementCustomizeProvider } from './ElementCustomizeProvider';
|
||||
import {
|
||||
ElementCustomizeForm,
|
||||
ElementCustomizeFormProps,
|
||||
} from './ElementCustomizerForm';
|
||||
import { ElementCustomizeTabsControllerProvider } from './ElementCustomizeTabsController';
|
||||
import { ElementCustomizeFields } from './ElementCustomizeFields';
|
||||
import { ElementCustomizePreview } from './ElementCustomizePreview';
|
||||
import { extractChildren } from '@/utils/extract-children';
|
||||
|
||||
export interface ElementCustomizeProps<T> extends ElementCustomizeFormProps<T> {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ElementCustomize<T>({
|
||||
initialValues,
|
||||
validationSchema,
|
||||
onSubmit,
|
||||
children,
|
||||
}: ElementCustomizeProps<T>) {
|
||||
const PaperTemplate = React.useMemo(
|
||||
() => extractChildren(children, ElementCustomize.PaperTemplate),
|
||||
[children],
|
||||
);
|
||||
const CustomizeTabs = React.useMemo(
|
||||
() => extractChildren(children, ElementCustomize.FieldsTab),
|
||||
[children],
|
||||
);
|
||||
|
||||
const value = { PaperTemplate, CustomizeTabs };
|
||||
|
||||
return (
|
||||
<ElementCustomizeForm
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<ElementCustomizeTabsControllerProvider>
|
||||
<ElementCustomizeProvider value={value}>
|
||||
<Group spacing={0} align="stretch">
|
||||
<ElementCustomizeFields />
|
||||
<ElementCustomizePreview />
|
||||
</Group>
|
||||
</ElementCustomizeProvider>
|
||||
</ElementCustomizeTabsControllerProvider>
|
||||
</ElementCustomizeForm>
|
||||
);
|
||||
}
|
||||
|
||||
export interface ElementCustomizePaperTemplateProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
ElementCustomize.PaperTemplate = ({
|
||||
children,
|
||||
}: ElementCustomizePaperTemplateProps) => {
|
||||
return <Box>{children}</Box>;
|
||||
};
|
||||
|
||||
export interface ElementCustomizeContentProps {
|
||||
id: string;
|
||||
label: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
ElementCustomize.FieldsTab = ({
|
||||
id,
|
||||
label,
|
||||
children,
|
||||
}: ElementCustomizeContentProps) => {
|
||||
return <Box>{children}</Box>;
|
||||
};
|
||||
@@ -2,28 +2,28 @@
|
||||
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 { Group, Stack } from '@/components';
|
||||
import { ElementCustomizeHeader } from './ElementCustomizeHeader';
|
||||
import { ElementCustomizeTabs } from './ElementCustomizeTabs';
|
||||
import { useElementCustomizeTabsController } from './ElementCustomizeTabsController';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useElementCustomizeContext } from './ElementCustomizeProvider';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import styles from './ElementCustomize.module.scss';
|
||||
|
||||
export function InvoiceCustomizeFields() {
|
||||
export function ElementCustomizeFields() {
|
||||
return (
|
||||
<Group spacing={0} align={'stretch'} className={styles.root}>
|
||||
<InvoiceCustomizeTabs />
|
||||
<InvoiceCustomizeFieldsMain />
|
||||
<Group spacing={0} align={'stretch'} className={styles.root}>
|
||||
<ElementCustomizeTabs />
|
||||
<ElementCustomizeFieldsMain />
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeFieldsMain() {
|
||||
const { currentTabId } = useInvoiceCustomizeTabsController();
|
||||
const { CustomizeTabs } = useInvoiceCustomizeContext();
|
||||
export function ElementCustomizeFieldsMain() {
|
||||
const { currentTabId } = useElementCustomizeTabsController();
|
||||
const { CustomizeTabs } = useElementCustomizeContext();
|
||||
|
||||
const CustomizeTabPanel = React.useMemo(
|
||||
() =>
|
||||
@@ -35,17 +35,17 @@ export function InvoiceCustomizeFieldsMain() {
|
||||
|
||||
return (
|
||||
<Stack spacing={0} className={styles.mainFields}>
|
||||
<InvoiceCustomizeHeader label={'Customize'} />
|
||||
<ElementCustomizeHeader label={'Customize'} />
|
||||
|
||||
<Stack spacing={0} style={{ flex: '1 1 auto', overflow: 'auto' }}>
|
||||
{CustomizeTabPanel}
|
||||
<InvoiceCustomizeFooterActions />
|
||||
<ElementCustomizeFooterActions />
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function InvoiceCustomizeFooterActionsRoot({ closeDrawer }) {
|
||||
function ElementCustomizeFooterActionsRoot({ closeDrawer }) {
|
||||
const { name } = useDrawerContext();
|
||||
const { submitForm } = useFormikContext();
|
||||
|
||||
@@ -70,6 +70,6 @@ function InvoiceCustomizeFooterActionsRoot({ closeDrawer }) {
|
||||
);
|
||||
}
|
||||
|
||||
const InvoiceCustomizeFooterActions = R.compose(withDrawerActions)(
|
||||
InvoiceCustomizeFooterActionsRoot,
|
||||
const ElementCustomizeFooterActions = R.compose(withDrawerActions)(
|
||||
ElementCustomizeFooterActionsRoot,
|
||||
);
|
||||
@@ -1,20 +1,20 @@
|
||||
import { Group, Icon } from '@/components';
|
||||
import { Button, Classes } from '@blueprintjs/core';
|
||||
import styles from './InvoiceCustomizeHeader.module.scss';
|
||||
import { Group, Icon } from '@/components';
|
||||
import styles from './ElementCustomizeHeader.module.scss';
|
||||
|
||||
interface InvoiceCustomizeHeaderProps {
|
||||
interface ElementCustomizeHeaderProps {
|
||||
label?: string;
|
||||
children?: React.ReactNode;
|
||||
closeButton?: boolean;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeHeader({
|
||||
export function ElementCustomizeHeader({
|
||||
label,
|
||||
closeButton,
|
||||
onClose,
|
||||
children,
|
||||
}: InvoiceCustomizeHeaderProps) {
|
||||
}: ElementCustomizeHeaderProps) {
|
||||
const handleClose = () => {
|
||||
onClose && onClose();
|
||||
};
|
||||
@@ -1,29 +1,32 @@
|
||||
// @ts-nocheck
|
||||
import * as R from 'ramda';
|
||||
import { Stack } from '@/components';
|
||||
import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader';
|
||||
import { InvoiceCustomizePreviewContent } from './InvoiceCustomizePreviewContent';
|
||||
import { ElementCustomizeHeader } from './ElementCustomizeHeader';
|
||||
import { ElementCustomizePreviewContent } from './ElementCustomizePreviewContent';
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
|
||||
function InvoiceCustomizePreviewRoot({ closeDrawer }) {
|
||||
function ElementCustomizePreviewRoot({ closeDrawer }) {
|
||||
const { name } = useDrawerContext();
|
||||
|
||||
const handleCloseBtnClick = () => {
|
||||
closeDrawer(name);
|
||||
};
|
||||
return (
|
||||
<Stack spacing={0} style={{ borderLeft: '1px solid #D9D9D9', height: '100vh', flex: '1 1' }}>
|
||||
<InvoiceCustomizeHeader
|
||||
<Stack
|
||||
spacing={0}
|
||||
style={{ borderLeft: '1px solid #D9D9D9', height: '100vh', flex: '1 1' }}
|
||||
>
|
||||
<ElementCustomizeHeader
|
||||
label={'Preview'}
|
||||
closeButton
|
||||
onClose={handleCloseBtnClick}
|
||||
/>
|
||||
<InvoiceCustomizePreviewContent />
|
||||
<ElementCustomizePreviewContent />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export const InvoiceCustomizePreview = R.compose(withDrawerActions)(
|
||||
InvoiceCustomizePreviewRoot,
|
||||
export const ElementCustomizePreview = R.compose(withDrawerActions)(
|
||||
ElementCustomizePreviewRoot,
|
||||
);
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Box } from '@/components';
|
||||
import { useInvoiceCustomizeContext } from './InvoiceCustomizeProvider';
|
||||
import { useElementCustomizeContext } from './ElementCustomizeProvider';
|
||||
|
||||
export function InvoiceCustomizePreviewContent() {
|
||||
const { PaperTemplate } = useInvoiceCustomizeContext();
|
||||
export function ElementCustomizePreviewContent() {
|
||||
const { PaperTemplate } = useElementCustomizeContext();
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -0,0 +1,32 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
|
||||
interface ElementCustomizeValue {
|
||||
PaperTemplate?: React.ReactNode;
|
||||
CustomizeTabs: React.ReactNode;
|
||||
}
|
||||
|
||||
const ElementCustomizeContext = createContext<ElementCustomizeValue>(
|
||||
{} as ElementCustomizeValue,
|
||||
);
|
||||
|
||||
export const ElementCustomizeProvider: React.FC<{
|
||||
value: ElementCustomizeValue;
|
||||
children: React.ReactNode;
|
||||
}> = ({ value, children }) => {
|
||||
return (
|
||||
<ElementCustomizeContext.Provider value={{ ...value }}>
|
||||
{children}
|
||||
</ElementCustomizeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useElementCustomizeContext = (): ElementCustomizeValue => {
|
||||
const context = useContext<ElementCustomizeValue>(ElementCustomizeContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useElementCustomize must be used within an ElementCustomizeProvider',
|
||||
);
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -1,28 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Box, Stack } from '@/components';
|
||||
import { Tab, Tabs } from '@blueprintjs/core';
|
||||
import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader';
|
||||
import { ElementCustomizeHeader } from './ElementCustomizeHeader';
|
||||
import {
|
||||
InvoiceCustomizeTabsEnum,
|
||||
useInvoiceCustomizeTabsController,
|
||||
} from './InvoiceCustomizeTabsController';
|
||||
import styles from './InvoiceCustomizeTabs.module.scss';
|
||||
import { useInvoiceCustomizeContext } from './InvoiceCustomizeProvider';
|
||||
import React from 'react';
|
||||
ElementCustomizeTabsEnum,
|
||||
useElementCustomizeTabsController,
|
||||
} from './ElementCustomizeTabsController';
|
||||
import { useElementCustomizeContext } from './ElementCustomizeProvider';
|
||||
import styles from './ElementCustomizeTabs.module.scss';
|
||||
|
||||
export function InvoiceCustomizeTabs() {
|
||||
const { setCurrentTabId } = useInvoiceCustomizeTabsController();
|
||||
export function ElementCustomizeTabs() {
|
||||
const { setCurrentTabId } = useElementCustomizeTabsController();
|
||||
|
||||
const { CustomizeTabs } = useInvoiceCustomizeContext();
|
||||
const { CustomizeTabs } = useElementCustomizeContext();
|
||||
|
||||
const tabItems = React.Children.map(CustomizeTabs, (node) => ({
|
||||
...(React.isValidElement(node) ? node.props : {}),
|
||||
}));
|
||||
const handleChange = (value: InvoiceCustomizeTabsEnum) => {
|
||||
const handleChange = (value: ElementCustomizeTabsEnum) => {
|
||||
setCurrentTabId(value);
|
||||
};
|
||||
return (
|
||||
<Stack spacing={0} className={styles.root}>
|
||||
<InvoiceCustomizeHeader label={''} />
|
||||
<ElementCustomizeHeader label={''} />
|
||||
|
||||
<Box className={styles.content}>
|
||||
<Tabs
|
||||
@@ -0,0 +1,46 @@
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
|
||||
export enum ElementCustomizeTabsEnum {
|
||||
General = 'general',
|
||||
Items = 'items',
|
||||
Totals = 'totals'
|
||||
}
|
||||
|
||||
const DEFAULT_TAB_ID = ElementCustomizeTabsEnum.General;
|
||||
|
||||
interface ElementCustomizeTabsControllerValue {
|
||||
currentTabId: ElementCustomizeTabsEnum;
|
||||
setCurrentTabId: React.Dispatch<
|
||||
React.SetStateAction<ElementCustomizeTabsEnum>
|
||||
>;
|
||||
}
|
||||
|
||||
const ElementCustomizeTabsController = createContext(
|
||||
{} as ElementCustomizeTabsControllerValue,
|
||||
);
|
||||
|
||||
export const useElementCustomizeTabsController = () => {
|
||||
return useContext(ElementCustomizeTabsController);
|
||||
};
|
||||
|
||||
interface ElementCustomizeTabsControllerProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ElementCustomizeTabsControllerProvider = ({
|
||||
children,
|
||||
}: ElementCustomizeTabsControllerProps) => {
|
||||
const [currentTabId, setCurrentTabId] =
|
||||
useState<ElementCustomizeTabsEnum>(DEFAULT_TAB_ID);
|
||||
|
||||
const value = {
|
||||
currentTabId,
|
||||
setCurrentTabId,
|
||||
};
|
||||
|
||||
return (
|
||||
<ElementCustomizeTabsController.Provider value={value}>
|
||||
{children}
|
||||
</ElementCustomizeTabsController.Provider>
|
||||
);
|
||||
};
|
||||
@@ -2,19 +2,19 @@
|
||||
import React from 'react';
|
||||
import { Formik, Form, FormikHelpers } from 'formik';
|
||||
|
||||
export interface InvoiceCustomizeFormProps<T> {
|
||||
export interface ElementCustomizeFormProps<T> {
|
||||
initialValues?: T;
|
||||
validationSchema?: any;
|
||||
onSubmit?: (values: T, formikHelpers: FormikHelpers<T>) => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export function InvoiceCustomizeForm<T>({
|
||||
export function ElementCustomizeForm<T>({
|
||||
initialValues,
|
||||
validationSchema,
|
||||
onSubmit,
|
||||
children,
|
||||
}: InvoiceCustomizeFormProps<T>) {
|
||||
}: ElementCustomizeFormProps<T>) {
|
||||
return (
|
||||
<Formik<T>
|
||||
initialValues={{ ...initialValues }}
|
||||
@@ -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,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,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,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,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