diff --git a/packages/server/src/interfaces/Ledger.ts b/packages/server/src/interfaces/Ledger.ts index 4e021718a..8af6ac8b8 100644 --- a/packages/server/src/interfaces/Ledger.ts +++ b/packages/server/src/interfaces/Ledger.ts @@ -41,6 +41,8 @@ export interface ILedgerEntry { index: number; indexGroup?: number; + note?: string; + userId?: number; itemId?: number; branchId?: number; diff --git a/packages/server/src/services/Accounting/utils.ts b/packages/server/src/services/Accounting/utils.ts index 081a0d14c..45a3de94e 100644 --- a/packages/server/src/services/Accounting/utils.ts +++ b/packages/server/src/services/Accounting/utils.ts @@ -21,6 +21,8 @@ export const transformLedgerEntryToTransaction = ( transactionNumber: entry.transactionNumber, referenceNumber: entry.referenceNumber, + note: entry.note, + index: entry.index, indexGroup: entry.indexGroup, diff --git a/packages/server/src/services/Cashflow/CashflowTransactionJournalEntries.ts b/packages/server/src/services/Cashflow/CashflowTransactionJournalEntries.ts index 93d23e3b1..21df84f34 100644 --- a/packages/server/src/services/Cashflow/CashflowTransactionJournalEntries.ts +++ b/packages/server/src/services/Cashflow/CashflowTransactionJournalEntries.ts @@ -25,8 +25,8 @@ export default class CashflowTransactionJournalEntries { /** * Retrieves the common entry of cashflow transaction. - * @param {ICashflowTransaction} cashflowTransaction - * @returns {} + * @param {ICashflowTransaction} cashflowTransaction + * @returns {Partial} */ private getCommonEntry = (cashflowTransaction: ICashflowTransaction) => { const { entries, ...transaction } = cashflowTransaction; @@ -41,7 +41,9 @@ export default class CashflowTransactionJournalEntries { ), transactionId: transaction.id, transactionNumber: transaction.transactionNumber, - referenceNo: transaction.referenceNo, + referenceNumber: transaction.referenceNo, + + note: transaction.description, branchId: cashflowTransaction.branchId, userId: cashflowTransaction.userId, @@ -76,9 +78,9 @@ export default class CashflowTransactionJournalEntries { /** * Retrieves the cashflow credit GL entry. - * @param {ICashflowTransaction} cashflowTransaction - * @param {ICashflowTransactionLine} entry - * @param {number} index + * @param {ICashflowTransaction} cashflowTransaction + * @param {ICashflowTransactionLine} entry + * @param {number} index * @returns {ILedgerEntry} */ private getCashflowCreditGLEntry = ( @@ -102,10 +104,10 @@ export default class CashflowTransactionJournalEntries { /** * Retrieves the cashflow transaction GL entry. - * @param {ICashflowTransaction} cashflowTransaction - * @param {ICashflowTransactionLine} entry - * @param {number} index - * @returns + * @param {ICashflowTransaction} cashflowTransaction + * @param {ICashflowTransactionLine} entry + * @param {number} index + * @returns {ILedgerEntry[]} */ private getJournalEntries = ( cashflowTransaction: ICashflowTransaction @@ -118,7 +120,7 @@ export default class CashflowTransactionJournalEntries { /** * Retrieves the cashflow GL ledger. - * @param {ICashflowTransaction} cashflowTransaction + * @param {ICashflowTransaction} cashflowTransaction * @returns {Ledger} */ private getCashflowLedger = (cashflowTransaction: ICashflowTransaction) => { @@ -130,6 +132,7 @@ export default class CashflowTransactionJournalEntries { * Write the journal entries of the given cashflow transaction. * @param {number} tenantId * @param {ICashflowTransaction} cashflowTransaction + * @return {Promise} */ public writeJournalEntries = async ( tenantId: number, @@ -153,6 +156,7 @@ export default class CashflowTransactionJournalEntries { * Delete the journal entries. * @param {number} tenantId - Tenant id. * @param {number} cashflowTransactionId - Cashflow transaction id. + * @return {Promise} */ public revertJournalEntries = async ( tenantId: number, diff --git a/packages/webapp/package-lock.json b/packages/webapp/package-lock.json index b7d381a9e..1c08f64d6 100644 --- a/packages/webapp/package-lock.json +++ b/packages/webapp/package-lock.json @@ -1,6 +1,6 @@ { "name": "@bigcapital/webapp", - "version": "1.7.1", + "version": "0.9.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1227,9 +1227,9 @@ } }, "@blueprintjs-formik/select": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.2.3.tgz", - "integrity": "sha512-j/zkX0B9wgtoHgK6Z/rlowB7F7zemrAajBU+d3caCoEYMMqwAI0XA++GytqrIhv5fEGjkZ1hkxS9j8eqX8vtjA==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.2.4.tgz", + "integrity": "sha512-zB28/hLkuO5zZXkjFmqfiVDGW+uvj9b8e6kHh9aOfY70edSFIfw3bj+NYR7BaDZoIYu3KuZQDFGqgs23ua5Z1g==", "requires": { "lodash.get": "^4.4.2", "lodash.keyby": "^4.6.0", diff --git a/packages/webapp/package.json b/packages/webapp/package.json index dc9228e83..4a46c7da5 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -5,7 +5,7 @@ "dependencies": { "@blueprintjs-formik/core": "^0.3.3", "@blueprintjs-formik/datetime": "^0.3.4", - "@blueprintjs-formik/select": "^0.2.3", + "@blueprintjs-formik/select": "^0.2.4", "@blueprintjs/core": "^3.50.2", "@blueprintjs/datetime": "^3.23.12", "@blueprintjs/popover2": "^0.11.1", diff --git a/packages/webapp/src/components/Customers/CustomerSelectField.tsx b/packages/webapp/src/components/Customers/CustomerSelectField.tsx deleted file mode 100644 index e7d5dce2a..000000000 --- a/packages/webapp/src/components/Customers/CustomerSelectField.tsx +++ /dev/null @@ -1,119 +0,0 @@ -// @ts-nocheck -import React, { useCallback, useState, useEffect, useMemo } from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import * as R from 'ramda'; - -import { MenuItem, Button } from '@blueprintjs/core'; -import { Select } from '@blueprintjs/select'; -import classNames from 'classnames'; -import { CLASSES } from '@/constants/classes'; - -import { - itemPredicate, - handleContactRenderer, - createNewItemRenderer, - createNewItemFromQuery, -} from './utils'; - -import withDrawerActions from '@/containers/Drawer/withDrawerActions'; - -import { DRAWERS } from '@/constants/drawers'; - -function CustomerSelectFieldRoot({ - // #withDrawerActions - openDrawer, - - // #ownProps - contacts, - initialContactId, - selectedContactId, - defaultSelectText = , - onContactSelected, - popoverFill = false, - disabled = false, - allowCreate, - buttonProps, - - ...restProps -}) { - const localContacts = useMemo( - () => - contacts.map((contact) => ({ - ...contact, - _id: `${contact.id}_${contact.contact_type}`, - })), - [contacts], - ); - - const initialContact = useMemo( - () => contacts.find((a) => a.id === initialContactId), - [initialContactId, contacts], - ); - - const [selecetedContact, setSelectedContact] = useState( - initialContact || null, - ); - - useEffect(() => { - if (typeof selectedContactId !== 'undefined') { - const account = selectedContactId - ? contacts.find((a) => a.id === selectedContactId) - : null; - setSelectedContact(account); - } - }, [selectedContactId, contacts, setSelectedContact]); - - const handleContactSelect = useCallback( - (contact) => { - if (contact.id) { - setSelectedContact({ ...contact }); - onContactSelected && onContactSelected(contact); - } else { - openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); - } - }, - [setSelectedContact, onContactSelected, openDrawer], - ); - - // Maybe inject create new item props to suggest component. - const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; - const maybeCreateNewItemFromQuery = allowCreate - ? createNewItemFromQuery - : null; - - return ( - - ); -} - -export const CustomerSelectField = R.compose(withDrawerActions)( - CustomerSelectFieldRoot, -); diff --git a/packages/webapp/src/components/Customers/CustomersSelect.tsx b/packages/webapp/src/components/Customers/CustomersSelect.tsx new file mode 100644 index 000000000..60e030314 --- /dev/null +++ b/packages/webapp/src/components/Customers/CustomersSelect.tsx @@ -0,0 +1,48 @@ +// @ts-nocheck +import React from 'react'; +import * as R from 'ramda'; +import { createNewItemFromQuery, createNewItemRenderer } from './utils'; +import { FSelect } from '../Forms'; +import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { DRAWERS } from '@/constants/drawers'; + +/** + * Customer select field. + * @returns {React.ReactNode} + */ +function CustomerSelectRoot({ + // #withDrawerActions + openDrawer, + + // #ownProps + items, + allowCreate, + ...props +}) { + // Maybe inject create new item props to suggest component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; + + // Handles the create item click. + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); + }; + + return ( + + ); +} + +export const CustomersSelect = R.compose(withDrawerActions)(CustomerSelectRoot); diff --git a/packages/webapp/src/components/Customers/index.tsx b/packages/webapp/src/components/Customers/index.tsx index eb057000f..aef111932 100644 --- a/packages/webapp/src/components/Customers/index.tsx +++ b/packages/webapp/src/components/Customers/index.tsx @@ -1,3 +1,3 @@ // @ts-nocheck -export * from './CustomerSelectField'; export * from './CustomerDrawerLink'; +export * from './CustomersSelect'; diff --git a/packages/webapp/src/components/Vendors/VendorSelectField.tsx b/packages/webapp/src/components/Vendors/VendorSelectField.tsx deleted file mode 100644 index 6883baccb..000000000 --- a/packages/webapp/src/components/Vendors/VendorSelectField.tsx +++ /dev/null @@ -1,118 +0,0 @@ -// @ts-nocheck -import React, { useCallback, useState, useEffect, useMemo } from 'react'; -import { FormattedMessage as T } from '@/components'; -import intl from 'react-intl-universal'; -import * as R from 'ramda'; - -import { MenuItem, Button } from '@blueprintjs/core'; -import { Select } from '@blueprintjs/select'; -import classNames from 'classnames'; -import { CLASSES } from '@/constants/classes'; - -import { - itemPredicate, - handleContactRenderer, - createNewItemFromQuery, - createNewItemRenderer, -} from './utils'; -import withDrawerActions from '@/containers/Drawer/withDrawerActions'; - -import { DRAWERS } from '@/constants/drawers'; - -function VendorSelectFieldRoot({ - // #withDrawerActions - openDrawer, - - // #ownProps - contacts, - initialContactId, - selectedContactId, - defaultSelectText = , - onContactSelected, - popoverFill = false, - disabled = false, - allowCreate, - buttonProps, - - ...restProps -}) { - const localContacts = useMemo( - () => - contacts.map((contact) => ({ - ...contact, - _id: `${contact.id}_${contact.contact_type}`, - })), - [contacts], - ); - - const initialContact = useMemo( - () => contacts.find((a) => a.id === initialContactId), - [initialContactId, contacts], - ); - - const [selecetedContact, setSelectedContact] = useState( - initialContact || null, - ); - - useEffect(() => { - if (typeof selectedContactId !== 'undefined') { - const account = selectedContactId - ? contacts.find((a) => a.id === selectedContactId) - : null; - setSelectedContact(account); - } - }, [selectedContactId, contacts, setSelectedContact]); - - const handleContactSelect = useCallback( - (contact) => { - if (contact.id) { - setSelectedContact({ ...contact }); - onContactSelected && onContactSelected(contact); - } else { - openDrawer(DRAWERS.QUICK_WRITE_VENDOR); - } - }, - [setSelectedContact, onContactSelected, openDrawer], - ); - - // Maybe inject create new item props to suggest component. - const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; - const maybeCreateNewItemFromQuery = allowCreate - ? createNewItemFromQuery - : null; - - return ( - - ); -} - -export const VendorSelectField = R.compose(withDrawerActions)( - VendorSelectFieldRoot, -); diff --git a/packages/webapp/src/components/Vendors/VendorsSelect.tsx b/packages/webapp/src/components/Vendors/VendorsSelect.tsx new file mode 100644 index 000000000..4b460d1f4 --- /dev/null +++ b/packages/webapp/src/components/Vendors/VendorsSelect.tsx @@ -0,0 +1,49 @@ +// @ts-nocheck +import React from 'react'; +import * as R from 'ramda'; +import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { createNewItemFromQuery, createNewItemRenderer } from './utils'; +import { FSelect } from '../Forms'; +import { DRAWERS } from '@/constants/drawers'; + +/** + * Vendor select. + * @returns {React.ReactNode} + */ +function VendorsSelectRoot({ + // #withDrawerActions + openDrawer, + + // #ownProps + items, + allowCreate, + + ...restProps +}) { + // Maybe inject create new item props to suggest component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; + + // Handles the create item click. + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_WRITE_VENDOR); + }; + + return ( + + ); +} + +export const VendorsSelect = R.compose(withDrawerActions)(VendorsSelectRoot); diff --git a/packages/webapp/src/components/Vendors/index.tsx b/packages/webapp/src/components/Vendors/index.tsx index a57d1571c..ae7471ccc 100644 --- a/packages/webapp/src/components/Vendors/index.tsx +++ b/packages/webapp/src/components/Vendors/index.tsx @@ -1,3 +1,3 @@ // @ts-nocheck export * from './VendorDrawerLink' -export * from './VendorSelectField' \ No newline at end of file +export * from './VendorsSelect'; \ No newline at end of file diff --git a/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.tsx b/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.tsx index ae9c18f2e..9a1f81a30 100644 --- a/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.tsx +++ b/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalEntriesHeaderFields.tsx @@ -1,14 +1,8 @@ // @ts-nocheck import React from 'react'; -import { - InputGroup, - FormGroup, - Position, - ControlGroup, -} from '@blueprintjs/core'; -import { FastField, ErrorMessage, useFormikContext } from 'formik'; +import { InputGroup, FormGroup, Position } from '@blueprintjs/core'; +import { FastField, ErrorMessage } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import * as R from 'ramda'; import classNames from 'classnames'; import { CLASSES } from '@/constants/classes'; @@ -20,99 +14,15 @@ import { } from '@/utils'; import { Hint, - FieldHint, FieldRequiredHint, Icon, - InputPrependButton, CurrencySelectList, FormattedMessage as T, - FInputGroup, - FFormGroup, } from '@/components'; import { useMakeJournalFormContext } from './MakeJournalProvider'; import { JournalExchangeRateInputField } from './components'; import { currenciesFieldShouldUpdate } from './utils'; - -import withSettings from '@/containers/Settings/withSettings'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; - -/** - * Journal number field of make journal form. - */ -const MakeJournalTransactionNoField = R.compose( - withDialogActions, - withSettings(({ manualJournalsSettings }) => ({ - journalAutoIncrement: manualJournalsSettings?.autoIncrement, - })), -)( - ({ - // #withDialog - openDialog, - - // #withSettings - journalAutoIncrement, - }) => { - const { setFieldValue, values } = useFormikContext(); - - const handleJournalNumberChange = () => { - openDialog('journal-number-form'); - }; - const handleJournalNoBlur = (event) => { - const newValue = event.target.value; - - if (values.journal_number !== newValue && journalAutoIncrement) { - openDialog('journal-number-form', { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - if (!journalAutoIncrement) { - setFieldValue('journal_number', newValue); - setFieldValue('journal_number_manually', newValue); - } - }; - - return ( - } - labelInfo={ - <> - - - - } - fill={true} - inline={true} - fastField={true} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: , - position: Position.BOTTOM_LEFT, - }} - /> - - - ); - }, -); +import { MakeJournalTransactionNoField } from './MakeJournalTransactionNoField'; /** * Make journal entries header. diff --git a/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalTransactionNoField.tsx b/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalTransactionNoField.tsx new file mode 100644 index 000000000..5aaaeda75 --- /dev/null +++ b/packages/webapp/src/containers/Accounting/MakeJournal/MakeJournalTransactionNoField.tsx @@ -0,0 +1,97 @@ +// @ts-nocheck +import React from 'react'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import * as R from 'ramda'; +import { + FieldHint, + FieldRequiredHint, + Icon, + InputPrependButton, + FormattedMessage as T, + FInputGroup, + FFormGroup, +} from '@/components'; + +import withSettings from '@/containers/Settings/withSettings'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; + +/** + * Journal number field of make journal form. + */ +export const MakeJournalTransactionNoField = R.compose( + withDialogActions, + withSettings(({ manualJournalsSettings }) => ({ + journalAutoIncrement: manualJournalsSettings?.autoIncrement, + })), +)( + ({ + // #withDialog + openDialog, + + // #withSettings + journalAutoIncrement, + }) => { + const { setFieldValue, values } = useFormikContext(); + + const handleJournalNumberChange = () => { + openDialog('journal-number-form'); + }; + const handleJournalNoBlur = (event) => { + const newValue = event.target.value; + + if (values.journal_number !== newValue && journalAutoIncrement) { + openDialog('journal-number-form', { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + if (!journalAutoIncrement) { + setFieldValue('journal_number', newValue); + setFieldValue('journal_number_manually', newValue); + } + }; + + return ( + } + labelInfo={ + <> + + + + } + fill={true} + inline={true} + fastField={true} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: , + position: Position.BOTTOM_LEFT, + }} + /> + + + ); + }, +); + +MakeJournalTransactionNoField.displayName = 'MakeJournalTransactionNoField'; diff --git a/packages/webapp/src/containers/CashFlow/MoneyInDialog/OtherIncome/OtherIncomeFormFields.tsx b/packages/webapp/src/containers/CashFlow/MoneyInDialog/OtherIncome/OtherIncomeFormFields.tsx index 30ad76e9b..d17b47615 100644 --- a/packages/webapp/src/containers/CashFlow/MoneyInDialog/OtherIncome/OtherIncomeFormFields.tsx +++ b/packages/webapp/src/containers/CashFlow/MoneyInDialog/OtherIncome/OtherIncomeFormFields.tsx @@ -99,6 +99,7 @@ export default function OtherIncomeFormFields() { )} + {/*------------ Transaction number -----------*/} diff --git a/packages/webapp/src/containers/Dialogs/QuickPaymentMadeFormDialog/utils.tsx b/packages/webapp/src/containers/Dialogs/QuickPaymentMadeFormDialog/utils.tsx index 1b659194d..b90e21da8 100644 --- a/packages/webapp/src/containers/Dialogs/QuickPaymentMadeFormDialog/utils.tsx +++ b/packages/webapp/src/containers/Dialogs/QuickPaymentMadeFormDialog/utils.tsx @@ -7,6 +7,7 @@ import { Intent } from '@blueprintjs/core'; import { AppToaster } from '@/components'; import { useFormikContext } from 'formik'; import { useQuickPaymentMadeContext } from './QuickPaymentMadeFormProvider'; +import { PAYMENT_MADE_ERRORS } from '@/containers/Purchases/PaymentMades/constants'; // Default initial values of payment made. export const defaultPaymentMade = { @@ -24,16 +25,16 @@ export const defaultPaymentMade = { export const transformErrors = (errors, { setFieldError }) => { const getError = (errorType) => errors.find((e) => e.type === errorType); - if (getError('PAYMENT.NUMBER.NOT.UNIQUE')) { + if (getError(PAYMENT_MADE_ERRORS.PAYMENT_NUMBER_NOT_UNIQUE)) { setFieldError('payment_number', intl.get('payment_number_is_not_unique')); } - if (getError('INVALID_BILL_PAYMENT_AMOUNT')) { + if (getError(PAYMENT_MADE_ERRORS.INVALID_BILL_PAYMENT_AMOUNT)) { setFieldError( 'payment_amount', intl.get('the_payment_amount_bigger_than_invoice_due_amount'), ); } - if (getError('WITHDRAWAL_ACCOUNT_CURRENCY_INVALID')) { + if (getError(PAYMENT_MADE_ERRORS.WITHDRAWAL_ACCOUNT_CURRENCY_INVALID)) { AppToaster.show({ message: intl.get( 'payment_made.error.withdrawal_account_currency_invalid', diff --git a/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerDetails.tsx b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerDetails.tsx index 4dec0dae4..22544b57b 100644 --- a/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerDetails.tsx +++ b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerDetails.tsx @@ -1,12 +1,13 @@ // @ts-nocheck import React from 'react'; -import { Card } from '@/components'; +import { Card, CommercialDocBox } from '@/components'; import CashflowTransactionDrawerActionBar from './CashflowTransactionDrawerActionBar'; import CashflowTransactionDrawerHeader from './CashflowTransactionDrawerHeader'; import CashflowTransactionDrawerTable from './CashflowTransactionDrawerTable'; -import CashflowTransactionDrawerFooter from './CashflowTransactionDrawerFooter'; +import CashflowTransactionDrawerTableFooter from './CashflowTransactionDrawerTableFooter'; +import { CashflowTransactionDrawerFooter } from './CashflowTransactionDrawerFooter'; /** * Cashflow transaction view details. */ @@ -16,11 +17,12 @@ export default function CashflowTransactionDrawerDetails() {
- + + - +
); diff --git a/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerFooter.tsx b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerFooter.tsx index 79c6a0706..b3a7ea58f 100644 --- a/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerFooter.tsx +++ b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerFooter.tsx @@ -1,35 +1,18 @@ // @ts-nocheck import React from 'react'; +import { CommercialDocFooter, DetailsMenu, DetailItem, T } from '@/components'; import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider'; -import { T, FormatNumber } from '@/components'; -export default function CashflowTransactionDrawerFooter() { - const { - cashflowTransaction: { formatted_amount }, - } = useCashflowTransactionDrawerContext(); +export function CashflowTransactionDrawerFooter() { + const { cashflowTransaction } = useCashflowTransactionDrawerContext(); return ( -
-
-
-
- -
-
- -
-
- -
-
-
-
- -
-
{formatted_amount}
-
{formatted_amount}
-
-
-
+ + + }> + {cashflowTransaction.description} + + + ); } diff --git a/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerTableFooter.tsx b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerTableFooter.tsx new file mode 100644 index 000000000..b46f6c0fe --- /dev/null +++ b/packages/webapp/src/containers/Drawers/CashflowTransactionDetailDrawer/CashflowTransactionDrawerTableFooter.tsx @@ -0,0 +1,35 @@ +// @ts-nocheck +import React from 'react'; +import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider'; +import { T, FormatNumber } from '@/components'; + +export default function CashflowTransactionDrawerTableFooter() { + const { + cashflowTransaction: { formatted_amount }, + } = useCashflowTransactionDrawerContext(); + + return ( +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
{formatted_amount}
+
{formatted_amount}
+
+
+
+ ); +} diff --git a/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailFooter.tsx b/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailFooter.tsx index fb1360c6d..237254652 100644 --- a/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailFooter.tsx +++ b/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailFooter.tsx @@ -1,6 +1,5 @@ // @ts-nocheck import React from 'react'; - import { CommercialDocFooter, T, diff --git a/packages/webapp/src/containers/Drawers/QuickCreateItemDrawer/QuickCreateItemDrawerForm.tsx b/packages/webapp/src/containers/Drawers/QuickCreateItemDrawer/QuickCreateItemDrawerForm.tsx index b185eacaa..29b7ec4a0 100644 --- a/packages/webapp/src/containers/Drawers/QuickCreateItemDrawer/QuickCreateItemDrawerForm.tsx +++ b/packages/webapp/src/containers/Drawers/QuickCreateItemDrawer/QuickCreateItemDrawerForm.tsx @@ -17,16 +17,6 @@ import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; import { useDrawerContext } from '@/components/Drawer/DrawerProvider'; import { DRAWERS } from '@/constants/drawers'; -/** - * Drawer item form loading. - * @returns {JSX} - */ -function DrawerItemFormLoading({ children }) { - const { isFormLoading } = useItemFormContext(); - - return {children}; -} - /** * Quick create/edit item drawer form. */ @@ -72,6 +62,16 @@ function QuickCreateItemDrawerForm({ ); } +/** + * Drawer item form loading. + * @returns {JSX} + */ +function DrawerItemFormLoading({ children }) { + const { isFormLoading } = useItemFormContext(); + + return {children}; +} + export default R.compose( withDrawerActions, withDashboardActions, @@ -79,10 +79,15 @@ export default R.compose( const ItemFormCard = styled(Card)` margin: 15px; + padding: 25px; margin-bottom: calc(15px + 65px); - .page-form__floating-actions { - margin-left: -36px; - margin-right: -36px; + .page-form { + padding: 0; + + &__floating-actions { + margin-left: -41px; + margin-right: -41px; + } } `; diff --git a/packages/webapp/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.tsx b/packages/webapp/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.tsx index 103a43b13..067bcda94 100644 --- a/packages/webapp/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Expenses/ExpenseForm/ExpenseFormHeaderFields.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { InputGroup, FormGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage } from 'formik'; -import { FormattedMessage as T } from '@/components'; +import { CustomersSelect, FormattedMessage as T } from '@/components'; import classNames from 'classnames'; import { CLASSES } from '@/constants/classes'; import { @@ -121,33 +121,39 @@ export default function ExpenseFormHeader() { )} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - inline={true} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - }} - allowCreate={true} - popoverFill={true} - /> - - )} - + {/* ----------- Customer ----------- */} + ); } + +/** + * Customer select field of expense form. + * @returns {React.ReactNode} + */ +function ExpenseFormCustomerSelect() { + const { customers } = useExpenseFormContext(); + + return ( + } + labelInfo={} + inline={true} + name={'customer_id'} + fastField={true} + shouldUpdateDeps={{ items: customers }} + shouldUpdate={customersFieldShouldUpdate} + > + } + allowCreate={true} + popoverFill={true} + fastField={true} + shouldUpdateDeps={{ items: customers }} + shouldUpdate={customersFieldShouldUpdate} + /> + + ); +} diff --git a/packages/webapp/src/containers/Expenses/ExpenseForm/utils.tsx b/packages/webapp/src/containers/Expenses/ExpenseForm/utils.tsx index ff27b127b..73c28bdad 100644 --- a/packages/webapp/src/containers/Expenses/ExpenseForm/utils.tsx +++ b/packages/webapp/src/containers/Expenses/ExpenseForm/utils.tsx @@ -104,7 +104,7 @@ export const transformToEditForm = ( */ export const customersFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Items/ItemFormFormik.tsx b/packages/webapp/src/containers/Items/ItemFormFormik.tsx index 3acf49da5..45bc74e92 100644 --- a/packages/webapp/src/containers/Items/ItemFormFormik.tsx +++ b/packages/webapp/src/containers/Items/ItemFormFormik.tsx @@ -90,7 +90,9 @@ export default function ItemFormFormik({ }; return ( -
+
{/*------------ Contact -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - - { - form.setFieldValue('contact_id', customer.id); - }} - allowCreate={true} - popoverFill={true} - /> - - )} - + {/*------------ Project Name -----------*/} + + + ); +} + export default ProjectFormFields; diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx index 7e051cb8b..0b797c2e5 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx @@ -2,18 +2,18 @@ import React from 'react'; import styled from 'styled-components'; import classNames from 'classnames'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { FormGroup, InputGroup, Classes, Position } from '@blueprintjs/core'; -import { FastField, ErrorMessage } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; + import { FeatureCan, FormattedMessage as T } from '@/components'; import { CLASSES } from '@/constants/classes'; - import { FFormGroup, - VendorSelectField, FieldRequiredHint, Icon, VendorDrawerLink, + VendorsSelect, } from '@/components'; import { useBillFormContext } from './BillFormProvider'; @@ -43,43 +43,7 @@ function BillFormHeader() { return (
{/* ------- Vendor name ------ */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames( - 'form-group--vendor-name', - 'form-group--select-list', - CLASSES.FILL, - )} - labelInfo={} - > - } - onContactSelected={(contact) => { - form.setFieldValue('vendor_id', contact.id); - form.setFieldValue('currency_code', contact?.currency_code); - }} - popoverFill={true} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + inline={true} + labelInfo={} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + > + } + onItemChange={(contact) => { + setFieldValue('vendor_id', contact.id); + setFieldValue('currency_code', contact?.currency_code); + }} + allowCreate={true} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + /> + {values.vendor_id && ( + + + + )} + + ); +} + export default compose(withDialogActions)(BillFormHeader); const VendorButtonLink = styled(VendorDrawerLink)` diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx index 272ea3a21..7e7cce017 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/utils.tsx @@ -19,7 +19,10 @@ import { ensureEntriesHaveEmptyLine, } from '@/containers/Entries/utils'; import { useCurrentOrganization } from '@/hooks/state'; -import { isLandedCostDisabled, getEntriesTotal } from '@/containers/Entries/utils'; +import { + isLandedCostDisabled, + getEntriesTotal, +} from '@/containers/Entries/utils'; import { useBillFormContext } from './BillFormProvider'; export const MIN_LINES_NUMBER = 1; @@ -153,7 +156,7 @@ export const handleDeleteErrors = (errors) => { */ export const vendorsFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.vendors !== oldProps.vendors || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx index e6db12915..89d76922f 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx @@ -9,17 +9,17 @@ import { ControlGroup, } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; -import { FastField, ErrorMessage } from 'formik'; +import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { CLASSES } from '@/constants/classes'; import { FFormGroup, - VendorSelectField, FieldRequiredHint, InputPrependButton, Icon, FormattedMessage as T, VendorDrawerLink, + VendorsSelect, } from '@/components'; import { vendorsFieldShouldUpdate, @@ -51,9 +51,6 @@ function VendorCreditNoteFormHeaderFields({ vendorcreditNumberPrefix, vendorcreditNextNumber, }) { - // Vendor Credit form context. - const { vendors } = useVendorCreditNoteFormContext(); - // Handle vendor credit number changing. const handleVendorCreditNumberChange = () => { openDialog('vendor-credit-form'); @@ -81,39 +78,7 @@ function VendorCreditNoteFormHeaderFields({ return (
{/* ----------- Vendor name ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames(CLASSES.FILL, 'form-group--vendor')} - labelInfo={} - > - } - onContactSelected={(contact) => { - form.setFieldValue('vendor_id', contact.id); - form.setFieldValue('currency_code', contact?.currency_code); - }} - popoverFill={true} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + inline={true} + labelInfo={} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + > + } + onItemChange={(contact) => { + setFieldValue('vendor_id', contact.id); + setFieldValue('currency_code', contact?.currency_code); + }} + popoverFill={true} + allowCreate={true} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + /> + {values.vendor_id && ( + + + + )} + + ); +} + export default compose( withDialogActions, withSettings(({ vendorsCreditNoteSetting }) => ({ diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx index 094f7bb55..db276ea11 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/utils.tsx @@ -113,7 +113,7 @@ export const transformFormValuesToRequest = (values) => { */ export const vendorsFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.vendors !== oldProps.vendors || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormFooterLeft.tsx b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormFooterLeft.tsx index 23b60eecf..8c119e60c 100644 --- a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormFooterLeft.tsx +++ b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormFooterLeft.tsx @@ -13,12 +13,14 @@ export function PaymentMadeFormFooterLeft() { {/* --------- Internal Note--------- */} } + fastField={true} > diff --git a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormHeaderFields.tsx b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormHeaderFields.tsx index 2023fcb41..6a72e9968 100644 --- a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormHeaderFields.tsx @@ -12,14 +12,13 @@ import { } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, Field, useFormikContext, ErrorMessage } from 'formik'; -import { FormattedMessage as T } from '@/components'; +import { FormattedMessage as T, VendorsSelect } from '@/components'; import { toSafeInteger } from 'lodash'; import { CLASSES } from '@/constants/classes'; import { FFormGroup, AccountsSelect, - VendorSelectField, FieldRequiredHint, InputPrependText, Money, @@ -55,8 +54,7 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) { } = useFormikContext(); // Payment made form context. - const { vendors, accounts, isNewMode, setPaymentVendorId } = - usePaymentMadeFormContext(); + const { accounts } = usePaymentMadeFormContext(); // Sumation of payable full-amount. const payableFullAmount = useMemo( @@ -82,41 +80,7 @@ function PaymentMadeFormHeaderFields({ organization: { base_currency } }) { return (
{/* ------------ Vendor name ------------ */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--select-list', Classes.FILL)} - labelInfo={} - > - } - onContactSelected={(contact) => { - form.setFieldValue('vendor_id', contact.id); - form.setFieldValue('currency_code', contact?.currency_code); - setPaymentVendorId(contact.id); - }} - disabled={!isNewMode} - popoverFill={true} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + labelInfo={} + inline={true} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + > + } + onItemChange={(contact) => { + setFieldValue('vendor_id', contact.id); + setFieldValue('currency_code', contact?.currency_code); + setPaymentVendorId(contact.id); + }} + disabled={!isNewMode} + allowCreate={true} + fastField={true} + shouldUpdate={vendorsFieldShouldUpdate} + shouldUpdateDeps={{ items: vendors }} + /> + {values.vendor_id && ( + + + + )} + + ); +} + export default compose(withCurrentOrganization())(PaymentMadeFormHeaderFields); const VendorButtonLink = styled(VendorDrawerLink)` diff --git a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/utils.tsx b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/utils.tsx index 2858e21ae..1b94ef4d6 100644 --- a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/utils.tsx +++ b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/utils.tsx @@ -15,6 +15,7 @@ import { formattedAmount, } from '@/utils'; import { useCurrentOrganization } from '@/hooks/state'; +import { PAYMENT_MADE_ERRORS } from '../constants'; export const ERRORS = { PAYMENT_NUMBER_NOT_UNIQUE: 'PAYMENT.NUMBER.NOT.UNIQUE', @@ -74,7 +75,7 @@ export const transformToNewPageEntries = (entries) => { */ export const vendorsFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.vendors !== oldProps.vendors || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; @@ -124,10 +125,10 @@ export const useSetPrimaryBranchToForm = () => { export const transformErrors = (errors, { setFieldError }) => { const getError = (errorType) => errors.find((e) => e.type === errorType); - if (getError('PAYMENT_NUMBER_NOT_UNIQUE')) { + if (getError(PAYMENT_MADE_ERRORS.PAYMENT_NUMBER_NOT_UNIQUE)) { setFieldError('payment_number', intl.get('payment_number_is_not_unique')); } - if (getError('WITHDRAWAL_ACCOUNT_CURRENCY_INVALID')) { + if (getError(PAYMENT_MADE_ERRORS.WITHDRAWAL_ACCOUNT_CURRENCY_INVALID)) { AppToaster.show({ message: intl.get( 'payment_made.error.withdrawal_account_currency_invalid', diff --git a/packages/webapp/src/containers/Purchases/PaymentMades/constants.ts b/packages/webapp/src/containers/Purchases/PaymentMades/constants.ts new file mode 100644 index 000000000..1813c867c --- /dev/null +++ b/packages/webapp/src/containers/Purchases/PaymentMades/constants.ts @@ -0,0 +1,5 @@ +export const PAYMENT_MADE_ERRORS = { + PAYMENT_NUMBER_NOT_UNIQUE: 'PAYMENT.NUMBER.NOT.UNIQUE', + WITHDRAWAL_ACCOUNT_CURRENCY_INVALID: 'WITHDRAWAL_ACCOUNT_CURRENCY_INVALID', + INVALID_BILL_PAYMENT_AMOUNT: 'INVALID_BILL_PAYMENT_AMOUNT' +}; diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx index fac113606..cd2fc1d1a 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx @@ -1,34 +1,25 @@ // @ts-nocheck import React from 'react'; -import * as R from 'ramda'; import classNames from 'classnames'; import styled from 'styled-components'; -import { - FormGroup, - InputGroup, - Position, - ControlGroup, -} from '@blueprintjs/core'; +import { FormGroup, InputGroup, Position } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { CLASSES } from '@/constants/classes'; import { - CustomerSelectField, FieldRequiredHint, - InputPrependButton, Icon, FormattedMessage as T, CustomerDrawerLink, FFormGroup, - FInputGroup, + CustomersSelect, } from '@/components'; import { customerNameFieldShouldUpdate } from './utils'; import { useCreditNoteFormContext } from './CreditNoteFormProvider'; -import withSettings from '@/containers/Settings/withSettings'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; import { CreditNoteExchangeRateInputField } from './components'; +import { CreditNoteTransactionNoField } from './CreditNoteTransactionNoField'; import { momentFormatter, tansformDateValue, @@ -36,134 +27,14 @@ import { handleDateChange, } from '@/utils'; -/** - * Credit note transaction number field. - */ -const CreditNoteTransactionNoField = R.compose( - withDialogActions, - withSettings(({ creditNoteSettings }) => ({ - creditAutoIncrement: creditNoteSettings?.autoIncrement, - creditNextNumber: creditNoteSettings?.nextNumber, - creditNumberPrefix: creditNoteSettings?.numberPrefix, - })), -)( - ({ - // #withDialogActions - openDialog, - - // #withSettings - creditAutoIncrement, - }) => { - const { values, setFieldValue } = useFormikContext(); - - // Handle credit number changing. - const handleCreditNumberChange = () => { - openDialog('credit-number-form'); - }; - // Handle credit note no. field blur. - const handleCreditNoBlur = (event) => { - const newValue = event.target.value; - - // Show the confirmation dialog if the value has changed and auto-increment - // mode is enabled. - if (values.credit_note_no !== newValue && creditAutoIncrement) { - openDialog('credit-number-form', { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - // Setting the credit note number to the form will be manually in case - // auto-increment is disable. - if (!creditAutoIncrement) { - setFieldValue('credit_note_number', newValue); - setFieldValue('credit_note_number_manually', newValue); - } - }; - - return ( - } - labelInfo={} - inline={true} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: ( - - ), - position: Position.BOTTOM_LEFT, - }} - /> - - - ); - }, -); - /** * Credit note form header fields. */ export default function CreditNoteFormHeaderFields({}) { - // Credit note form context. - const { customers } = useCreditNoteFormContext(); - return (
{/* ----------- Customer name ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames( - 'form-group--customer-name', - 'form-group--select-list', - CLASSES.FILL, - )} - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - form.setFieldValue('currency_code', customer?.currency_code); - }} - popoverFill={true} - allowCreate={true} - /> - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + labelInfo={} + inline={true} + fastField={true} + shouldUpdate={customerNameFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + > + } + onItemChange={(customer) => { + setFieldValue('customer_id', customer.id); + setFieldValue('currency_code', customer?.currency_code); + }} + popoverFill={true} + allowCreate={true} + fastField={true} + shouldUpdate={customerNameFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + /> + {values.customer_id && ( + + + + )} + + ); +} + const CustomerButtonLink = styled(CustomerDrawerLink)` font-size: 11px; margin-top: 6px; diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteTransactionNoField.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteTransactionNoField.tsx new file mode 100644 index 000000000..ffccc308c --- /dev/null +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteTransactionNoField.tsx @@ -0,0 +1,98 @@ +// @ts-nocheck +import React from 'react'; +import * as R from 'ramda'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import { + FieldRequiredHint, + InputPrependButton, + Icon, + FormattedMessage as T, + FFormGroup, + FInputGroup, +} from '@/components'; +import withSettings from '@/containers/Settings/withSettings'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; + +/** + * Credit note transaction number field. + */ +export const CreditNoteTransactionNoField = R.compose( + withDialogActions, + withSettings(({ creditNoteSettings }) => ({ + creditAutoIncrement: creditNoteSettings?.autoIncrement, + creditNextNumber: creditNoteSettings?.nextNumber, + creditNumberPrefix: creditNoteSettings?.numberPrefix, + })), +)( + ({ + // #withDialogActions + openDialog, + + // #withSettings + creditAutoIncrement, + }) => { + const { values, setFieldValue } = useFormikContext(); + + // Handle credit number changing. + const handleCreditNumberChange = () => { + openDialog('credit-number-form'); + }; + // Handle credit note no. field blur. + const handleCreditNoBlur = (event) => { + const newValue = event.target.value; + + // Show the confirmation dialog if the value has changed and auto-increment + // mode is enabled. + if (values.credit_note_no !== newValue && creditAutoIncrement) { + openDialog('credit-number-form', { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + // Setting the credit note number to the form will be manually in case + // auto-increment is disable. + if (!creditAutoIncrement) { + setFieldValue('credit_note_number', newValue); + setFieldValue('credit_note_number_manually', newValue); + } + }; + + return ( + } + labelInfo={} + inline={true} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: ( + + ), + position: Position.BOTTOM_LEFT, + }} + /> + + + ); + }, +); + +CreditNoteTransactionNoField.displayName = 'CreditNoteTransactionNoField'; diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx index 11ffb118d..2200146de 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/utils.tsx @@ -116,7 +116,7 @@ export const transformFormValuesToRequest = (values) => { */ export const customerNameFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormEstimateNumberField.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormEstimateNumberField.tsx new file mode 100644 index 000000000..b4c9c7495 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormEstimateNumberField.tsx @@ -0,0 +1,92 @@ +// @ts-nocheck +import React from 'react'; +import * as R from 'ramda'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import { + FFormGroup, + FInputGroup, + FormattedMessage as T, + Icon, + InputPrependButton, +} from '@/components'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withSettings from '@/containers/Settings/withSettings'; + +/** + * Estimate number field of estimate form. + */ +export const EstimateFormEstimateNumberField = R.compose( + withDialogActions, + withSettings(({ estimatesSettings }) => ({ + estimateNextNumber: estimatesSettings?.nextNumber, + estimateNumberPrefix: estimatesSettings?.numberPrefix, + estimateAutoIncrement: estimatesSettings?.autoIncrement, + })), +)( + ({ + // #withDialogActions + openDialog, + + // #withSettings + estimateAutoIncrement, + }) => { + const { values, setFieldValue } = useFormikContext(); + + const handleEstimateNumberBtnClick = () => { + openDialog('estimate-number-form', {}); + }; + // Handle estimate no. field blur. + const handleEstimateNoBlur = (event) => { + const newValue = event.target.value; + + // Show the confirmation dialog if the value has changed and auto-increment + // mode is enabled. + if (values.estimate_number !== newValue && estimateAutoIncrement) { + openDialog('estimate-number-form', { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + // Setting the estimate number to the form will be manually in case + // auto-increment is disable. + if (!estimateAutoIncrement) { + setFieldValue('estimate_number', newValue); + setFieldValue('estimate_number_manually', newValue); + } + }; + + return ( + } + inline={true} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: , + position: Position.BOTTOM_LEFT, + }} + /> + + + ); + }, +); + +EstimateFormEstimateNumberField.displayName = 'EstimateFormEstimateNumberField'; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx index 70444babc..e3bfabb9a 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx @@ -1,28 +1,19 @@ // @ts-nocheck import React from 'react'; -import * as R from 'ramda'; import styled from 'styled-components'; import classNames from 'classnames'; -import { - FormGroup, - InputGroup, - Position, - Classes, - ControlGroup, -} from '@blueprintjs/core'; +import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; import { FeatureCan, FFormGroup, - FInputGroup, FormattedMessage as T, - CustomerSelectField, FieldRequiredHint, Icon, - InputPrependButton, CustomerDrawerLink, + CustomersSelect, } from '@/components'; import { momentFormatter, @@ -34,92 +25,14 @@ import { customersFieldShouldUpdate } from './utils'; import { CLASSES } from '@/constants/classes'; import { Features } from '@/constants'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; -import withSettings from '@/containers/Settings/withSettings'; - import { ProjectsSelect } from '@/containers/Projects/components'; import { EstimateExchangeRateInputField, EstimateProjectSelectButton, } from './components'; +import { EstimateFormEstimateNumberField } from './EstimateFormEstimateNumberField'; import { useEstimateFormContext } from './EstimateFormProvider'; -/** - * Estimate number field of estimate form. - */ -const EstimateFormEstimateNumberField = R.compose( - withDialogActions, - withSettings(({ estimatesSettings }) => ({ - estimateNextNumber: estimatesSettings?.nextNumber, - estimateNumberPrefix: estimatesSettings?.numberPrefix, - estimateAutoIncrement: estimatesSettings?.autoIncrement, - })), -)( - ({ - // #withDialogActions - openDialog, - - // #withSettings - estimateAutoIncrement, - }) => { - const { values, setFieldValue } = useFormikContext(); - - const handleEstimateNumberBtnClick = () => { - openDialog('estimate-number-form', {}); - }; - // Handle estimate no. field blur. - const handleEstimateNoBlur = (event) => { - const newValue = event.target.value; - - // Show the confirmation dialog if the value has changed and auto-increment - // mode is enabled. - if (values.estimate_number !== newValue && estimateAutoIncrement) { - openDialog('estimate-number-form', { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - // Setting the estimate number to the form will be manually in case - // auto-increment is disable. - if (!estimateAutoIncrement) { - setFieldValue('estimate_number', newValue); - setFieldValue('estimate_number_manually', newValue); - } - }; - - return ( - } - inline={true} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: , - position: Position.BOTTOM_LEFT, - }} - /> - - - ); - }, -); - /** * Estimate form header. */ @@ -129,41 +42,7 @@ export default function EstimateFormHeader() { return (
{/* ----------- Customer name ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames(CLASSES.FILL, 'form-group--customer')} - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - form.setFieldValue('currency_code', customer?.currency_code); - }} - popoverFill={true} - intent={inputIntent({ error, touched })} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange Rate ----------- */} } + inline={true} + labelInfo={} + name={'customer_id'} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + > + } + onItemChange={(customer) => { + setFieldValue('customer_id', customer.id); + setFieldValue('currency_code', customer?.currency_code); + }} + popoverFill={true} + allowCreate={true} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + /> + {values.customer_id && ( + + + + )} + + ); +} + const CustomerButtonLink = styled(CustomerDrawerLink)` font-size: 11px; margin-top: 6px; diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx index cf2fb74b6..029a3a70d 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/utils.tsx @@ -80,7 +80,7 @@ export const transformToEditForm = (estimate) => { */ export const customersFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx index 1fd9b5317..8697e52bc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx @@ -2,16 +2,9 @@ import React from 'react'; import styled from 'styled-components'; import classNames from 'classnames'; -import { - FormGroup, - InputGroup, - Position, - Classes, - ControlGroup, -} from '@blueprintjs/core'; +import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; -import * as R from 'ramda'; import { FFormGroup, @@ -19,12 +12,9 @@ import { Col, Row, CustomerDrawerLink, - CustomerSelectField, FieldRequiredHint, - Icon, - InputPrependButton, FeatureCan, - FInputGroup, + CustomersSelect, } from '@/components'; import { momentFormatter, @@ -40,143 +30,25 @@ import { InvoiceExchangeRateInputField, InvoiceProjectSelectButton, } from './components'; +import { InvoiceFormInvoiceNumberField } from './InvoiceFormInvoiceNumberField'; import { ProjectsSelect, ProjectBillableEntriesLink, } from '@/containers/Projects/components'; import { Features } from '@/constants'; -import { DialogsName } from '@/constants/dialogs'; - -import withSettings from '@/containers/Settings/withSettings'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; - -/** - * Invoice number field of invoice form. - */ -const InvoiceFormInvoiceNumberField = R.compose( - withDialogActions, - withSettings(({ invoiceSettings }) => ({ - invoiceAutoIncrement: invoiceSettings?.autoIncrement, - })), -)( - ({ - // #withDialogActions - openDialog, - - // #withSettings - invoiceAutoIncrement, - }) => { - // Formik context. - const { values, setFieldValue } = useFormikContext(); - - // Handle invoice number changing. - const handleInvoiceNumberChange = () => { - openDialog(DialogsName.InvoiceNumberSettings); - }; - // Handle invoice no. field blur. - const handleInvoiceNoBlur = (event) => { - const newValue = event.target.value; - - // Show the confirmation dialog if the value has changed and auto-increment - // mode is enabled. - if (values.invoice_no !== newValue && invoiceAutoIncrement) { - openDialog(DialogsName.InvoiceNumberSettings, { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - // Setting the invoice number to the form will be manually in case - // auto-increment is disable. - if (!invoiceAutoIncrement) { - setFieldValue('invoice_no', newValue); - setFieldValue('invoice_no_manually', newValue); - } - }; - - return ( - } - labelInfo={} - inline={true} - fastField={true} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: , - position: Position.BOTTOM_LEFT, - }} - /> - - - ); - }, -); -InvoiceFormInvoiceNumberField.displayName = 'InvoiceFormInvoiceNumberField'; /** * Invoice form header fields. */ export default function InvoiceFormHeaderFields() { // Invoice form context. - const { customers, projects } = useInvoiceFormContext(); + const { projects } = useInvoiceFormContext(); const { values } = useFormikContext(); return (
{/* ----------- Customer name ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames( - 'form-group--customer-name', - 'form-group--select-list', - CLASSES.FILL, - )} - labelInfo={} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - form.setFieldValue('currency_code', customer?.currency_code); - }} - popoverFill={true} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + inline={true} + labelInfo={} + fastField={true} + shouldUpdate={customerNameFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + > + } + onItemChange={(customer) => { + setFieldValue('customer_id', customer.id); + setFieldValue('currency_code', customer?.currency_code); + }} + allowCreate={true} + fastField={true} + shouldUpdate={customerNameFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + /> + {values.customer_id && ( + + + + )} + + ); +} + const CustomerButtonLink = styled(CustomerDrawerLink)` font-size: 11px; margin-top: 6px; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormInvoiceNumberField.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormInvoiceNumberField.tsx new file mode 100644 index 000000000..8fc086777 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormInvoiceNumberField.tsx @@ -0,0 +1,95 @@ +// @ts-nocheck +import React from 'react'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import * as R from 'ramda'; +import { + FFormGroup, + FormattedMessage as T, + FieldRequiredHint, + Icon, + InputPrependButton, + FInputGroup, +} from '@/components'; +import { DialogsName } from '@/constants/dialogs'; +import withSettings from '@/containers/Settings/withSettings'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; + +/** + * Invoice number field of invoice form. + */ +export const InvoiceFormInvoiceNumberField = R.compose( + withDialogActions, + withSettings(({ invoiceSettings }) => ({ + invoiceAutoIncrement: invoiceSettings?.autoIncrement, + })), +)( + ({ + // #withDialogActions + openDialog, + + // #withSettings + invoiceAutoIncrement, + }) => { + // Formik context. + const { values, setFieldValue } = useFormikContext(); + + // Handle invoice number changing. + const handleInvoiceNumberChange = () => { + openDialog(DialogsName.InvoiceNumberSettings); + }; + // Handle invoice no. field blur. + const handleInvoiceNoBlur = (event) => { + const newValue = event.target.value; + + // Show the confirmation dialog if the value has changed and auto-increment + // mode is enabled. + if (values.invoice_no !== newValue && invoiceAutoIncrement) { + openDialog(DialogsName.InvoiceNumberSettings, { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + // Setting the invoice number to the form will be manually in case + // auto-increment is disable. + if (!invoiceAutoIncrement) { + setFieldValue('invoice_no', newValue); + setFieldValue('invoice_no_manually', newValue); + } + }; + + return ( + } + labelInfo={} + inline={true} + fastField={true} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: , + position: Position.BOTTOM_LEFT, + }} + /> + + + ); + }, +); +InvoiceFormInvoiceNumberField.displayName = 'InvoiceFormInvoiceNumberField'; diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx index 536f0081c..4af9dabb9 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/utils.tsx @@ -114,7 +114,7 @@ export const transformErrors = (errors, { setErrors }) => { */ export const customerNameFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items|| defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.tsx index 0aea4912b..8c139e655 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveFormFootetLeft.tsx @@ -7,25 +7,18 @@ import { FFormGroup, FEditableText, FormattedMessage as T } from '@/components'; export function PaymentReceiveFormFootetLeft() { return ( - {/* --------- Statement--------- */} - } - > - - - {/* --------- Internal Note--------- */} } + fastField={true} > @@ -43,17 +36,3 @@ const TermsConditsFormGroup = styled(FFormGroup)` } } `; - -const PaymentMsgFormGroup = styled(FFormGroup)` - &.bp3-form-group { - margin-bottom: 40px; - - .bp3-label { - font-size: 12px; - margin-bottom: 12px; - } - .bp3-form-content { - margin-left: 10px; - } - } -`; diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx index 96ac9462e..9ed1e5503 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx @@ -13,10 +13,12 @@ import { import { DateInput } from '@blueprintjs/datetime'; import { toSafeInteger } from 'lodash'; import { FastField, Field, useFormikContext, ErrorMessage } from 'formik'; -import * as R from 'ramda'; -import { FInputGroup, FeatureCan, FormattedMessage as T } from '@/components'; -import { useAutofocus } from '@/hooks'; +import { + FeatureCan, + CustomersSelect, + FormattedMessage as T, +} from '@/components'; import { CLASSES } from '@/constants/classes'; import { safeSumBy, @@ -28,10 +30,8 @@ import { import { FFormGroup, AccountsSelect, - CustomerSelectField, FieldRequiredHint, Icon, - InputPrependButton, MoneyInputGroup, InputPrependText, CustomerDrawerLink, @@ -46,9 +46,6 @@ import { PaymentReceiveProjectSelectButton, } from './components'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; -import withSettings from '@/containers/Settings/withSettings'; - import { amountPaymentEntries, fullAmountPaymentEntries, @@ -56,95 +53,14 @@ import { accountsFieldShouldUpdate, } from './utils'; import { Features } from '@/constants'; - -/** - * Payment receive number field. - */ -const PaymentReceivePaymentNoField = R.compose( - withSettings(({ paymentReceiveSettings }) => ({ - paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement, - })), - withDialogActions, -)( - ({ - // #withDialogActions - openDialog, - - // #withSettings - paymentReceiveAutoIncrement, - }) => { - const { values, setFieldValue } = useFormikContext(); - - // Handle click open payment receive number dialog. - const handleClickOpenDialog = () => { - openDialog('payment-receive-number-form'); - }; - // Handle payment number field blur. - const handlePaymentNoBlur = (event) => { - const newValue = event.target.value; - - // Show the confirmation dialog if the value has changed and auto-increment - // mode is enabled. - if ( - values.payment_receive_no !== newValue && - paymentReceiveAutoIncrement - ) { - openDialog('payment-receive-number-form', { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - // Setting the payment number to the form will be manually in case - // auto-increment is disable. - if (!paymentReceiveAutoIncrement) { - setFieldValue('payment_receive_no', newValue); - setFieldValue('payment_receive_no_manually', newValue); - } - }; - return ( - } - inline={true} - labelInfo={} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: ( - - ), - position: Position.BOTTOM_LEFT, - }} - /> - - - ); - }, -); +import { PaymentReceivePaymentNoField } from './PaymentReceivePaymentNoField'; /** * Payment receive header fields. */ export default function PaymentReceiveHeaderFields() { // Payment receive form context. - const { customers, accounts, projects, isNewMode } = - usePaymentReceiveFormContext(); + const { accounts, projects } = usePaymentReceiveFormContext(); // Formik form context. const { @@ -152,8 +68,6 @@ export default function PaymentReceiveHeaderFields() { setFieldValue, } = useFormikContext(); - const customerFieldRef = useAutofocus(); - // Calculates the full-amount received. const totalDueAmount = useMemo( () => safeSumBy(entries, 'due_amount'), @@ -176,45 +90,7 @@ export default function PaymentReceiveHeaderFields() { return (
{/* ------------- Customer name ------------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames('form-group--select-list', CLASSES.FILL)} - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - form.setFieldValue('full_amount', ''); - form.setFieldValue('currency_code', customer?.currency_code); - }} - popoverFill={true} - disabled={!isNewMode} - buttonProps={{ - elementRef: (ref) => (customerFieldRef.current = ref), - }} - allowCreate={true} - /> - - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + inline={true} + labelInfo={} + name={'customer_id'} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + > + } + onItemChange={(customer) => { + setFieldValue('customer_id', customer.id); + setFieldValue('full_amount', ''); + setFieldValue('currency_code', customer?.currency_code); + }} + popoverFill={true} + disabled={!isNewMode} + allowCreate={true} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + /> + {values.customer_id && ( + + + + )} + + ); +} diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceivePaymentNoField.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceivePaymentNoField.tsx new file mode 100644 index 000000000..e695013c7 --- /dev/null +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceivePaymentNoField.tsx @@ -0,0 +1,99 @@ +// @ts-nocheck +import React, { useMemo } from 'react'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import * as R from 'ramda'; + +import { FInputGroup, FormattedMessage as T } from '@/components'; +import { + FFormGroup, + FieldRequiredHint, + Icon, + InputPrependButton, +} from '@/components'; + +import withDialogActions from '@/containers/Dialog/withDialogActions'; +import withSettings from '@/containers/Settings/withSettings'; + +/** + * Payment receive number field. + */ +export const PaymentReceivePaymentNoField = R.compose( + withSettings(({ paymentReceiveSettings }) => ({ + paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement, + })), + withDialogActions, +)( + ({ + // #withDialogActions + openDialog, + + // #withSettings + paymentReceiveAutoIncrement, + }) => { + const { values, setFieldValue } = useFormikContext(); + + // Handle click open payment receive number dialog. + const handleClickOpenDialog = () => { + openDialog('payment-receive-number-form'); + }; + // Handle payment number field blur. + const handlePaymentNoBlur = (event) => { + const newValue = event.target.value; + + // Show the confirmation dialog if the value has changed and auto-increment + // mode is enabled. + if ( + values.payment_receive_no !== newValue && + paymentReceiveAutoIncrement + ) { + openDialog('payment-receive-number-form', { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + // Setting the payment number to the form will be manually in case + // auto-increment is disable. + if (!paymentReceiveAutoIncrement) { + setFieldValue('payment_receive_no', newValue); + setFieldValue('payment_receive_no_manually', newValue); + } + }; + return ( + } + inline={true} + labelInfo={} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: ( + + ), + position: Position.BOTTOM_LEFT, + }} + /> + + + ); + }, +); + +PaymentReceivePaymentNoField.displayName = 'PaymentReceivePaymentNoField'; diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.tsx index ec33a1b64..900eb9f9a 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/utils.tsx @@ -129,7 +129,7 @@ export const fullAmountPaymentEntries = (entries) => { */ export const customersFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx index ff62e984a..92ef297cb 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx @@ -2,16 +2,9 @@ import React, { useCallback } from 'react'; import styled from 'styled-components'; import classNames from 'classnames'; -import { - FormGroup, - InputGroup, - Position, - Classes, - ControlGroup, -} from '@blueprintjs/core'; +import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; import { FastField, ErrorMessage, useFormikContext } from 'formik'; -import * as R from 'ramda'; import { CLASSES } from '@/constants/classes'; import { ACCOUNT_TYPE } from '@/constants/accountTypes'; @@ -19,14 +12,12 @@ import { Features } from '@/constants'; import { FFormGroup, AccountsSelect, - CustomerSelectField, + CustomersSelect, FieldRequiredHint, Icon, - InputPrependButton, CustomerDrawerLink, FormattedMessage as T, FeatureCan, - FInputGroup, } from '@/components'; import { ProjectsSelect } from '@/containers/Projects/components'; import { @@ -41,133 +32,18 @@ import { ReceiptExchangeRateInputField, ReceiptProjectSelectButton, } from './components'; - -import withSettings from '@/containers/Settings/withSettings'; -import withDialogActions from '@/containers/Dialog/withDialogActions'; - -/** - * Receipt number field of receipt form. - */ -const ReceiptFormReceiptNumberField = R.compose( - withDialogActions, - withSettings(({ receiptSettings }) => ({ - receiptAutoIncrement: receiptSettings?.autoIncrement, - })), -)( - ({ - // #withDialogActions - openDialog, - - // #withSettings - receiptAutoIncrement, - }) => { - const { values, setFieldValue } = useFormikContext(); - - const handleReceiptNumberChange = () => { - openDialog('receipt-number-form', {}); - }; - - const handleReceiptNoBlur = (event) => { - const newValue = event.target.value; - - // Show the confirmation dialog if the value has changed and auto-increment - // mode is enabled. - if (values.receipt_number !== newValue && receiptAutoIncrement) { - openDialog('receipt-number-form', { - initialFormValues: { - onceManualNumber: newValue, - incrementMode: 'manual-transaction', - }, - }); - } - // Setting the receipt number to the form will be manually in case - // auto-increment is disable. - if (!receiptAutoIncrement) { - setFieldValue('receipt_number', newValue); - setFieldValue('receipt_number_manually', newValue); - } - }; - - return ( - } - inline={true} - labelInfo={} - > - - {}} - /> - , - }} - tooltip={true} - tooltipProps={{ - content: ( - - ), - position: Position.BOTTOM_LEFT, - }} - inputProps={{ - leftIcon: , - }} - /> - - - ); - }, -); +import { ReceiptFormReceiptNumberField } from './ReceiptFormReceiptNumberField'; /** * Receipt form header fields. */ export default function ReceiptFormHeader() { - const { accounts, customers, projects } = useReceiptFormContext(); + const { accounts, projects } = useReceiptFormContext(); return (
{/* ----------- Customer name ----------- */} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - inline={true} - className={classNames(CLASSES.FILL, 'form-group--customer')} - labelInfo={} - intent={inputIntent({ error, touched })} - helperText={} - > - } - onContactSelected={(customer) => { - form.setFieldValue('customer_id', customer.id); - form.setFieldValue('currency_code', customer?.currency_code); - }} - popoverFill={true} - allowCreate={true} - /> - {value && ( - - - - )} - - )} - + {/* ----------- Exchange rate ----------- */} } + labelInfo={} + inline={true} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + > + } + onItemChange={(customer) => { + setFieldValue('customer_id', customer.id); + setFieldValue('currency_code', customer?.currency_code); + }} + popoverFill={true} + allowCreate={true} + fastField={true} + shouldUpdate={customersFieldShouldUpdate} + shouldUpdateDeps={{ items: customers }} + /> + {values.customer_id && ( + + + + )} + + ); +} + const CustomerButtonLink = styled(CustomerDrawerLink)` font-size: 11px; margin-top: 6px; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormReceiptNumberField.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormReceiptNumberField.tsx new file mode 100644 index 000000000..7846cf898 --- /dev/null +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormReceiptNumberField.tsx @@ -0,0 +1,99 @@ +// @ts-nocheck +import React from 'react'; +import { Position, ControlGroup } from '@blueprintjs/core'; +import { useFormikContext } from 'formik'; +import * as R from 'ramda'; +import { + FFormGroup, + FieldRequiredHint, + Icon, + InputPrependButton, + FormattedMessage as T, + FInputGroup, +} from '@/components'; + +import withSettings from '@/containers/Settings/withSettings'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; + +/** + * Receipt number field of receipt form. + */ +export const ReceiptFormReceiptNumberField = R.compose( + withDialogActions, + withSettings(({ receiptSettings }) => ({ + receiptAutoIncrement: receiptSettings?.autoIncrement, + })), +)( + ({ + // #withDialogActions + openDialog, + + // #withSettings + receiptAutoIncrement, + }) => { + const { values, setFieldValue } = useFormikContext(); + + const handleReceiptNumberChange = () => { + openDialog('receipt-number-form', {}); + }; + + const handleReceiptNoBlur = (event) => { + const newValue = event.target.value; + + // Show the confirmation dialog if the value has changed and auto-increment + // mode is enabled. + if (values.receipt_number !== newValue && receiptAutoIncrement) { + openDialog('receipt-number-form', { + initialFormValues: { + onceManualNumber: newValue, + incrementMode: 'manual-transaction', + }, + }); + } + // Setting the receipt number to the form will be manually in case + // auto-increment is disable. + if (!receiptAutoIncrement) { + setFieldValue('receipt_number', newValue); + setFieldValue('receipt_number_manually', newValue); + } + }; + + return ( + } + inline={true} + labelInfo={} + > + + {}} + /> + , + }} + tooltip={true} + tooltipProps={{ + content: ( + + ), + position: Position.BOTTOM_LEFT, + }} + inputProps={{ + leftIcon: , + }} + /> + + + ); + }, +); + +ReceiptFormReceiptNumberField.displayName = 'ReceiptFormReceiptNumberField'; diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx index 4dcaec4b2..b1f766d3b 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/utils.tsx @@ -104,7 +104,7 @@ export const accountsFieldShouldUpdate = (newProps, oldProps) => { */ export const customersFieldShouldUpdate = (newProps, oldProps) => { return ( - newProps.customers !== oldProps.customers || + newProps.shouldUpdateDeps.items !== oldProps.shouldUpdateDeps.items || defaultFastFieldShouldUpdate(newProps, oldProps) ); }; diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json index 60cacb3a0..ed0537d77 100644 --- a/packages/webapp/src/lang/en/index.json +++ b/packages/webapp/src/lang/en/index.json @@ -379,7 +379,7 @@ "the_expenses_have_been_deleted_successfully": "The expenses have been deleted successfully", "once_delete_these_expenses_you_will_not_able_restore_them": "Once you delete these expenses, you won't be able to retrieve them later. Are you sure you want to delete them?", "the_expense_has_been_published": "The expense has been published", - "select_customer": "Select customer", + "select_customer": "Select Customer...", "total_amount_equals_zero": "Total amount equals zero", "value": "Value", "you_reached_conditions_limit": "You have reached to conditions limit.", @@ -480,7 +480,7 @@ "estimate_date": "Estimate Date", "expiration_date": "Expiration Date", "customer_note": "Customer Note", - "select_customer_account": "Select Customer Account", + "select_customer_account": "Select Customer Account...", "select_product": "Select Product", "reference": "Reference #", "clear": "Clear", @@ -1452,6 +1452,7 @@ "cash_flow.setting_your_auto_generated_transaction_number": "Setting your auto-generated transaction number", "cash_flow_drawer.label_transaction_type": "Transaction type", "cash_flow.drawer.label_transaction_no": "Transaction number", + "cash_flow.drawer.label.statement": "Statement", "cash_flow.drawer.label_transaction": "Cash flow Transaction {number}", "cash_flow.account_transactions.no_results": "There are no deposit/withdrawal transactions on the current account.", "cash_flow_balance_in": "Balance in {name}",