From f5e9485a12e3638d0c845bbe400790b4b98ed74f Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 8 Sep 2024 17:34:19 +0200 Subject: [PATCH] feat: wip invoice customize --- .../InvoiceCustomize/ColorField.module.scss | 5 +- .../Invoices/InvoiceCustomize/ColorField.tsx | 62 ++++++++++++++++-- .../Invoices/InvoiceCustomize/FColorField.tsx | 65 +++++++++++++++++-- .../InvoiceCustomizeContent.tsx | 2 +- .../InvoiceCustomizeDrawer.tsx | 2 +- .../InvoiceCustomizeFields.module.scss | 12 ++++ .../InvoiceCustomizeFields.tsx | 45 +++++++++++-- .../InvoiceCustomizeGeneralFields.tsx | 44 ++++++++++--- .../InvoiceCustomizeHeader.module.scss | 1 + .../InvoiceCustomizeHeader.tsx | 2 +- .../InvoiceCustomizePreview.tsx | 23 ++++++- .../InvoiceCustomizePreviewContent.tsx | 2 +- .../InvoiceCustomizeTabs.module.scss | 7 ++ .../InvoiceCustomize/InvoiceCustomizeTabs.tsx | 14 ++-- .../InvoiceCutomizeContentFields.tsx | 37 +++++++++++ 15 files changed, 287 insertions(+), 36 deletions(-) create mode 100644 packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCutomizeContentFields.tsx diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.module.scss b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.module.scss index a018fb5c9..f0f737129 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.module.scss +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.module.scss @@ -8,7 +8,8 @@ .colorPicker{ background-color: rgb(103, 114, 229); border-radius: 3px; - height: 14px; - width: 14px; + height: 16px; + width: 16px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); cursor: pointer; } \ No newline at end of file diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.tsx index 3f18db7e1..719fc714c 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/ColorField.tsx @@ -1,29 +1,79 @@ +import { useState } from 'react'; +import clsx from 'classnames'; import { + IInputGroupProps, InputGroup, + IPopoverProps, Popover, PopoverInteractionKind, Position, } from '@blueprintjs/core'; -import { useState } from 'react'; import { HexColorPicker } from 'react-colorful'; +import { useUncontrolled } from '@/hooks/useUncontrolled'; +import { Box, BoxProps } from '@/components'; import styles from './ColorField.module.scss'; -export function ColorField() { - const [color, setColor] = useState('#aabbcc'); +export interface ColorFieldProps { + value?: string; + initialValue?: string; + onChange?: (value: string) => void; + popoverProps?: Partial; + inputProps?: Partial; + pickerProps?: Partial; + pickerWrapProps?: Partial; +} + +export function ColorField({ + value, + initialValue, + onChange, + popoverProps, + inputProps, + pickerWrapProps, + pickerProps, +}: ColorFieldProps) { + const [_value, handleChange] = useUncontrolled({ + value, + initialValue, + onChange, + finalValue: '', + }); + const [isOpen, setIsOpen] = useState(false); + + const handleClose = () => { + setIsOpen(false); + }; return ( } + content={} position={Position.BOTTOM} interactionKind={PopoverInteractionKind.CLICK} modifiers={{ offset: { offset: '0, 4' }, }} + onClose={handleClose} + isOpen={isOpen} minimal + {...popoverProps} > } - className={styles.field} + value={_value} + leftElement={ + + setIsOpen((oldValue) => !oldValue)} + style={{ backgroundColor: _value }} + className={clsx(styles.colorPicker, pickerProps?.className)} + {...pickerProps} + /> + + } + {...inputProps} + className={clsx(styles.field, inputProps?.className)} /> ); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/FColorField.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/FColorField.tsx index fc2008a77..35840f7cb 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/FColorField.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/FColorField.tsx @@ -1,9 +1,64 @@ -import { ColorField } from './ColorField'; +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 FColorFieldProps { - name: string; +interface ColorFieldInputGroupProps + extends Omit, + ColorFieldProps {} + +export interface ColorFieldToInputProps + extends Omit, + 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, + }; } -export function FColorField({ name }: FColorFieldProps) { - return ; +/** + * Transforms field props to input group props for ColorField. + * @param {ColorFieldToInputProps} props - + * @returns {JSX.Element} + */ +function ColorFieldToInputGroup({ + ...props +}: ColorFieldToInputProps): JSX.Element { + return ; +} + +/** + * Input group Blueprint component binded with Formik for ColorField. + * @param {ColorFieldInputGroupProps} + * @returns {JSX.Element} + */ +export function FColorInput({ + ...props +}: ColorFieldInputGroupProps): JSX.Element { + return ; } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeContent.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeContent.tsx index 00f1933b2..31ce04ad7 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeContent.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeContent.tsx @@ -9,7 +9,7 @@ export default function InvoiceCustomizeContent() { return ( - + diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeDrawer.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeDrawer.tsx index e4e8dbe2c..04aa9143a 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeDrawer.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeDrawer.tsx @@ -1,7 +1,6 @@ // @ts-nocheck import React from 'react'; import * as R from 'ramda'; - import { Drawer, DrawerSuspense } from '@/components'; import withDrawers from '@/containers/Drawer/withDrawers'; @@ -25,6 +24,7 @@ function InvoiceCustomizeDrawerRoot({ name={name} size={'100%'} > + diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.module.scss b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.module.scss index 4159c65a9..7222b3187 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.module.scss +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.module.scss @@ -4,4 +4,16 @@ .mainFields{ flex: 1; +} +.fieldGroup { + + :global .bp4-form-content{ + margin-left: auto; + } +} + +.footerActions{ + padding: 10px 16px; + border-top: 1px solid #d9d9d9; + flex-flow: row-reverse; } \ No newline at end of file diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.tsx index a50011509..094e308dc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeFields.tsx @@ -1,9 +1,16 @@ -import { Box, Group } from '@/components'; +// @ts-nocheck +import * as R from 'ramda'; +import { Box, Group, Stack } from '@/components'; import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader'; import { InvoiceCustomizeTabs } from './InvoiceCustomizeTabs'; import styles from './InvoiceCustomizeFields.module.scss'; import { InvoiceCustomizeGeneralField } from './InvoiceCustomizeGeneralFields'; import { useInvoiceCustomizeTabsController } from './InvoiceCustomizeTabsController'; +import { Button, Intent } from '@blueprintjs/core'; +import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { useDrawerContext } from '@/components/Drawer/DrawerProvider'; +import { useFormikContext } from 'formik'; +import { InvoiceCustomizeContentFields } from './InvoiceCutomizeContentFields'; export function InvoiceCustomizeFields() { return ( @@ -17,10 +24,40 @@ export function InvoiceCustomizeFields() { export function InvoiceCustomizeFieldsMain() { const { currentTabId } = useInvoiceCustomizeTabsController(); return ( - + - {currentTabId === 'general' && } - + + {currentTabId === 'general' && } + {currentTabId === 'content' && } + + + + ); } + +function InvoiceCustomizeFooterActionsRoot({ closeDrawer }) { + const { name } = useDrawerContext(); + const { submitForm } = useFormikContext(); + + const handleSubmitBtnClick = () => { + submitForm(); + }; + const handleCancelBtnClick = () => { + closeDrawer(name); + }; + + return ( + + + + + ); +} + +const InvoiceCustomizeFooterActions = R.compose(withDrawerActions)( + InvoiceCustomizeFooterActionsRoot, +); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeGeneralFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeGeneralFields.tsx index 2870741ad..cd3e3039c 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeGeneralFields.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeGeneralFields.tsx @@ -1,16 +1,44 @@ -import { Box, FFormGroup } from '@/components'; -import { FColorField } from './FColorField'; +import { Box, FFormGroup, FSwitch, Stack } from '@/components'; +import { FColorInput } from './FColorField'; +import styles from './InvoiceCustomizeFields.module.scss'; +import { Classes } from '@blueprintjs/core'; export function InvoiceCustomizeGeneralField() { return ( - - - + + +

General Branding

+

+ Set your invoice details to be automatically applied every time
you + create a new invoice. +

+
+ + + - - + + -
+ + + + + ); } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.module.scss b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.module.scss index 28d3fa50d..afca06e9b 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.module.scss +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.module.scss @@ -9,6 +9,7 @@ padding: 5px 5px 5px 20px; position: relative; background-color: #fff; + z-index: 1; } .title{ diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.tsx index 6e6fd1816..0dc6e209c 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeHeader.tsx @@ -1,6 +1,6 @@ import { Group, Icon } from '@/components'; -import styles from './InvoiceCustomizeHeader.module.scss'; import { Button, Classes } from '@blueprintjs/core'; +import styles from './InvoiceCustomizeHeader.module.scss'; interface InvoiceCustomizeHeaderProps { label?: string; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreview.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreview.tsx index 8ae9a84a0..b6460bf2d 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreview.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreview.tsx @@ -1,12 +1,29 @@ +// @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'; -export function InvoiceCustomizePreview() { +function InvoiceCustomizePreviewRoot({ closeDrawer }) { + const { name } = useDrawerContext(); + + const handleCloseBtnClick = () => { + closeDrawer(name); + }; return ( - - + + ); } + +export const InvoiceCustomizePreview = R.compose(withDrawerActions)( + InvoiceCustomizePreviewRoot, +); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreviewContent.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreviewContent.tsx index 91df2434c..0e526ccee 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreviewContent.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizePreviewContent.tsx @@ -3,7 +3,7 @@ import { PaperTemplate } from './PaperTemplate'; export function InvoiceCustomizePreviewContent() { return ( - + ); diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.module.scss b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.module.scss index 6ca316672..2d928e745 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.module.scss +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.module.scss @@ -7,8 +7,15 @@ .content{ padding: 5px; + flex: 1; + border-right: 1px solid #E1E1E1; } .tabsList{ width: 100%; + flex: 1; + + :global .bp4-tab-list{ + flex: 1; + } } \ No newline at end of file diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.tsx index c5bcabcb0..0d02843b1 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCustomizeTabs.tsx @@ -1,4 +1,4 @@ -import { Box } from '@/components'; +import { Box, Stack } from '@/components'; import { Tab, Tabs } from '@blueprintjs/core'; import { InvoiceCustomizeHeader } from './InvoiceCustomizeHeader'; import styles from './InvoiceCustomizeTabs.module.scss'; @@ -14,16 +14,22 @@ export function InvoiceCustomizeTabs() { setCurrentTabId(value); }; return ( - + - + - + ); } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCutomizeContentFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCutomizeContentFields.tsx new file mode 100644 index 000000000..ba58df5a3 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceCustomize/InvoiceCutomizeContentFields.tsx @@ -0,0 +1,37 @@ +import { FInputGroup, FSwitch, Group, Stack } from '@/components'; +import { Classes } from '@blueprintjs/core'; + +const items = [ + { key: 'dueAmount', label: 'Due Amount' }, + { key: 'billedTo', label: 'Billed To' }, + { key: 'balanceDue', label: 'Balance Due' }, + { key: 'termsConditions', label: 'Terms & Conditions' }, +]; + +export function InvoiceCustomizeContentFields() { + return ( + + +

General Branding

+

+ Set your invoice details to be automatically applied every time
you + create a new invoice. +

+
+ +

Header

+ + + {items.map((item, index) => ( + + + + + ))} + +
+ ); +}