From 68a0db91ee1653d9f9b20f804d9656c4184673c3 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 13 Oct 2024 13:56:13 +0200 Subject: [PATCH] feat: form header fields --- packages/webapp/src/components/App.tsx | 2 +- .../CreditNoteFormHeaderFields.tsx | 45 +++-- .../EstimateForm/EstimateFormHeaderFields.tsx | 47 +++-- .../Invoices/InvoiceForm/InvoiceForm.tsx | 13 +- .../InvoiceForm/InvoiceFormHeaderFields.tsx | 161 ++++++++++-------- .../InvoiceItemsEntriesEditorField.tsx | 56 +++--- .../PaymentReceiveFormHeader.tsx | 3 +- .../PaymentReceiveHeaderFields.tsx | 53 +++++- .../ReceiptForm/ReceiptFormHeader.tsx | 1 + .../ReceiptForm/ReceiptFormHeaderFields.tsx | 53 ++++-- 10 files changed, 263 insertions(+), 171 deletions(-) diff --git a/packages/webapp/src/components/App.tsx b/packages/webapp/src/components/App.tsx index a962d88f7..8e3ace04f 100644 --- a/packages/webapp/src/components/App.tsx +++ b/packages/webapp/src/components/App.tsx @@ -40,7 +40,7 @@ const PaymentPortalPage = lazy( const theme = { ...defaultTheme, - // Customize your theme here + bpPrefix: 'bp4', } /** diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx index 3c89f2f04..ad5bca1df 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx @@ -5,6 +5,8 @@ import styled from 'styled-components'; import { FormGroup, InputGroup, Position } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; +import { css } from '@emotion/css'; +import { useTheme } from '@emotion/react'; import { CLASSES } from '@/constants/classes'; import { @@ -14,6 +16,7 @@ import { CustomerDrawerLink, FFormGroup, CustomersSelect, + Stack, } from '@/components'; import { customerNameFieldShouldUpdate } from './utils'; @@ -28,12 +31,31 @@ import { } from '@/utils'; import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc'; +const getCreditNoteFieldsStyle = (theme: Theme) => css` + .${theme.bpPrefix}-form-group { + margin-bottom: 0; + + &.${theme.bpPrefix}-inline { + max-width: 450px; + } + .${theme.bpPrefix}-label { + min-width: 150px; + } + .${theme.bpPrefix}-form-content { + width: 100%; + } + } +`; + /** * Credit note form header fields. */ -export default function CreditNoteFormHeaderFields({}) { +export default function CreditNoteFormHeaderFields() { + const theme = useTheme(); + const styleClassName = getCreditNoteFieldsStyle(theme); + return ( -
+ {/* ----------- Customer name ----------- */} @@ -65,24 +87,15 @@ export default function CreditNoteFormHeaderFields({}) { )} + {/* ----------- Credit note # ----------- */} {/* ----------- Reference ----------- */} - - {({ field, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--reference', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - -
+ } name={'reference_no'} inline> + + + ); } diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx index eba6eb5da..fb04e904f 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx @@ -1,10 +1,10 @@ // @ts-nocheck import styled from 'styled-components'; import classNames from 'classnames'; -import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core'; +import { FormGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; - +import { css } from '@emotion/css'; import { FeatureCan, FFormGroup, @@ -13,6 +13,8 @@ import { Icon, CustomerDrawerLink, CustomersSelect, + FInputGroup, + Stack, } from '@/components'; import { momentFormatter, @@ -31,15 +33,36 @@ import { import { EstimateFormEstimateNumberField } from './EstimateFormEstimateNumberField'; import { useEstimateFormContext } from './EstimateFormProvider'; import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc'; +import { useTheme } from '@emotion/react'; +import { Theme } from '@xstyled/emotion'; + +const getEstimateFieldsStyle = (theme: Theme) => css` + .${theme.bpPrefix}-form-group { + margin-bottom: 0; + + &.${theme.bpPrefix}-inline { + max-width: 470px; + } + .${theme.bpPrefix}-label { + min-width: 160px; + font-weight: 500; + } + .${theme.bpPrefix}-form-content { + width: 100%; + } + } +`; /** * Estimate form header. */ export default function EstimateFormHeader() { + const theme = useTheme(); const { projects } = useEstimateFormContext(); + const styleClassName = getEstimateFieldsStyle(theme); return ( -
+ {/* ----------- Customer name ----------- */} @@ -106,19 +129,9 @@ export default function EstimateFormHeader() { {/* ----------- Reference ----------- */} - - {({ form, field, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--reference', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - + } inline fill> + + {/*------------ Project name -----------*/} @@ -136,7 +149,7 @@ export default function EstimateFormHeader() { /> -
+ ); } diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx index 2a410aed3..8359be8d9 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceForm.tsx @@ -22,7 +22,7 @@ import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; import withSettings from '@/containers/Settings/withSettings'; import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization'; -import { AppToaster } from '@/components'; +import { AppToaster, Box } from '@/components'; import { compose, orderingLinesIndexes, transactionNumber } from '@/utils'; import { useInvoiceFormContext } from './InvoiceFormProvider'; import { InvoiceFormActions } from './InvoiceFormActions'; @@ -166,20 +166,23 @@ function InvoiceFormRoot({ initialValues={initialValues} onSubmit={handleSubmit} > -
- - + + + + + diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx index 8b6bc5fd2..8facf34e8 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx @@ -2,20 +2,23 @@ import React from 'react'; import styled from 'styled-components'; import classNames from 'classnames'; -import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core'; +import { FormGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; +import { css } from '@emotion/css'; +import { Theme, useTheme } from '@emotion/react'; import { FFormGroup, FormattedMessage as T, - Col, - Row, CustomerDrawerLink, FieldRequiredHint, FeatureCan, CustomersSelect, - Stack + Stack, + Group, + FInputGroup, + Icon, } from '@/components'; import { momentFormatter, @@ -39,97 +42,105 @@ import { import { Features } from '@/constants'; import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc'; +const getInvoiceFieldsStyle = (theme: Theme) => css` + .${theme.bpPrefix}-form-group { + margin-bottom: 0; + + &.${theme.bpPrefix}-inline { + max-width: 450px; + } + .${theme.bpPrefix}-label { + min-width: 150px; + font-weight: 500; + } + .${theme.bpPrefix}-form-content { + width: 100%; + } + } +`; + /** * Invoice form header fields. */ export default function InvoiceFormHeaderFields() { - // Invoice form context. + const theme = useTheme(); const { projects } = useInvoiceFormContext(); const { values } = useFormikContext(); + const invoiceFieldsClassName = getInvoiceFieldsStyle(theme); return ( - + {/* ----------- Customer name ----------- */} {/* ----------- Exchange rate ----------- */} - - - {/* ----------- Invoice date ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - labelInfo={} - className={classNames('form-group--invoice-date', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - { - form.setFieldValue('invoice_date', formattedDate); - })} - popoverProps={{ - position: Position.BOTTOM_LEFT, - minimal: true, - }} - /> - - )} - - + {/* ----------- Invoice date ----------- */} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + inline={true} + labelInfo={} + className={classNames(CLASSES.FILL)} + intent={inputIntent({ error, touched })} + helperText={} + > + { + form.setFieldValue('invoice_date', formattedDate); + })} + popoverProps={{ + position: Position.BOTTOM_LEFT, + minimal: true, + }} + inputProps={{ + leftIcon: , + }} + /> + + )} + - - {/* ----------- Due date ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - labelInfo={} - inline={true} - className={classNames('form-group--due-date', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - { - form.setFieldValue('due_date', formattedDate); - })} - popoverProps={{ - position: Position.BOTTOM_LEFT, - minimal: true, - }} - /> - - )} - - - + {/* ----------- Due date ----------- */} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + labelInfo={} + inline={true} + className={classNames(CLASSES.FILL)} + intent={inputIntent({ error, touched })} + helperText={} + > + { + form.setFieldValue('due_date', formattedDate); + })} + popoverProps={{ + position: Position.BOTTOM_LEFT, + minimal: true, + }} + inputProps={{ + leftIcon: , + }} + /> + + )} + {/* ----------- Invoice number ----------- */} {/* ----------- Reference ----------- */} - - {({ field, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--reference', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - + } inline> + + {/*------------ Project name -----------*/} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceItemsEntriesEditorField.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceItemsEntriesEditorField.tsx index aa907de30..6fa4d9911 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceItemsEntriesEditorField.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceItemsEntriesEditorField.tsx @@ -15,35 +15,31 @@ export default function InvoiceItemsEntriesEditorField() { const { items, taxRates } = useInvoiceFormContext(); return ( - - - {({ - form: { values, setFieldValue }, - field: { value }, - meta: { error, touched }, - }) => ( - { - setFieldValue('entries', entries); - }} - items={items} - taxRates={taxRates} - itemType={ITEM_TYPE.SELLABLE} - errors={error} - linesNumber={4} - currencyCode={values.currency_code} - isInclusiveTax={ - values.inclusive_exclusive_tax === TaxType.Inclusive - } - /> - )} - - + + {({ + form: { values, setFieldValue }, + field: { value }, + meta: { error, touched }, + }) => ( + { + setFieldValue('entries', entries); + }} + items={items} + taxRates={taxRates} + itemType={ITEM_TYPE.SELLABLE} + errors={error} + linesNumber={4} + currencyCode={values.currency_code} + isInclusiveTax={values.inclusive_exclusive_tax === TaxType.Inclusive} + /> + )} + ); } diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveFormHeader.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveFormHeader.tsx index 2a587444d..d0596564f 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveFormHeader.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveFormHeader.tsx @@ -1,7 +1,6 @@ // @ts-nocheck -import React, { useMemo } from 'react'; +import React from 'react'; import classNames from 'classnames'; -import { sumBy } from 'lodash'; import { useFormikContext } from 'formik'; import { Group, Money } from '@/components'; import { FormattedMessage as T } from '@/components'; diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx index 71ff9bfc8..42f956aa7 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx @@ -13,12 +13,15 @@ import { import { DateInput } from '@blueprintjs/datetime'; import { isEmpty, toSafeInteger } from 'lodash'; import { FastField, useFormikContext, ErrorMessage } from 'formik'; +import { css } from '@emotion/css'; +import { Theme, useTheme } from '@emotion/react'; import { FeatureCan, CustomersSelect, FormattedMessage as T, FMoneyInputGroup, + Stack, } from '@/components'; import { CLASSES } from '@/constants/classes'; import { @@ -55,10 +58,30 @@ import { import { Features } from '@/constants'; import { PaymentReceivePaymentNoField } from './PaymentReceivePaymentNoField'; + +const getHeaderFieldsStyle = (theme: Theme) => css` + .${theme.bpPrefix}-form-group { + margin-bottom: 0; + + &.${theme.bpPrefix}-inline { + max-width: 470px; + } + .${theme.bpPrefix}-label { + min-width: 160px; + } + .${theme.bpPrefix}-form-content { + width: 100%; + } + } +`; + /** * Payment receive header fields. */ export default function PaymentReceiveHeaderFields() { + const theme = useTheme(); + const styleClassName = getHeaderFieldsStyle(theme); + // Payment receive form context. const { accounts, projects } = usePaymentReceiveFormContext(); @@ -88,7 +111,7 @@ export default function PaymentReceiveHeaderFields() { }; return ( -
+ {/* ------------- Customer name ------------- */} @@ -143,9 +166,25 @@ export default function PaymentReceiveHeaderFields() { {!isEmpty(entries) && (
+
); } diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeader.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeader.tsx index fd2f8e678..9c6d8ac2e 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeader.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeader.tsx @@ -20,6 +20,7 @@ function ReceiptFormHeader({ display="flex" bg="white" p="25px 32px" + borderBottom="1px solid #d2dce2" > css` + .${theme.bpPrefix}-form-group { + margin-bottom: 0; + + &.${theme.bpPrefix}-inline { + max-width: 450px; + } + .${theme.bpPrefix}-label { + min-width: 150px; + font-weight: 500; + } + .${theme.bpPrefix}-form-content { + width: 100%; + } + } +`; + /** * Receipt form header fields. */ export default function ReceiptFormHeader() { + const theme = useTheme(); + const receiptFieldsClassName = getEstimateFieldsStyle(theme); const { accounts, projects } = useReceiptFormContext(); return ( -
+ {/* ----------- Customer name ----------- */} @@ -104,19 +127,13 @@ export default function ReceiptFormHeader() { {/* ----------- Reference ----------- */} - - {({ field, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--reference', CLASSES.FILL)} - intent={inputIntent({ error, touched })} - helperText={} - > - - - )} - + } + inline={true} + name={'reference_no'} + > + + {/*------------ Project name -----------*/} @@ -134,7 +151,7 @@ export default function ReceiptFormHeader() { /> -
+
); }