feat(webapp): refactor customer and vendor select component

This commit is contained in:
Ahmed Bouhuolia
2023-06-22 17:26:33 +02:00
parent ca4d543482
commit eadaac30d6
16 changed files with 495 additions and 607 deletions

View File

@@ -22,6 +22,7 @@ import {
CustomerDrawerLink,
FFormGroup,
FInputGroup,
CustomersSelect,
} from '@/components';
import { customerNameFieldShouldUpdate } from './utils';
@@ -121,49 +122,10 @@ const CreditNoteTransactionNoField = R.compose(
* Credit note form header fields.
*/
export default function CreditNoteFormHeaderFields({}) {
// Credit note form context.
const { customers } = useCreditNoteFormContext();
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}
<FastField
name={'customer_id'}
customers={customers}
shouldUpdate={customerNameFieldShouldUpdate}
>
{({ form, field: { value }, meta: { error, touched } }) => (
<FormGroup
label={<T id={'customer_name'} />}
inline={true}
className={classNames(
'form-group--customer-name',
'form-group--select-list',
CLASSES.FILL,
)}
labelInfo={<FieldRequiredHint />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'customer_id'} />}
>
<CustomerSelectField
contacts={customers}
selectedContactId={value}
defaultSelectText={<T id={'select_customer_account'} />}
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
/>
{value && (
<CustomerButtonLink customerId={value}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FormGroup>
)}
</FastField>
<CreditNoteCustomersSelect />
{/* ----------- Exchange rate ----------- */}
<CreditNoteExchangeRateInputField
@@ -216,6 +178,45 @@ export default function CreditNoteFormHeaderFields({}) {
);
}
/**
* Customer select field of credit note form.
* @returns {React.ReactNode}
*/
function CreditNoteCustomersSelect() {
// Credit note form context.
const { customers } = useCreditNoteFormContext();
const { setFieldValue, values } = useFormikContext();
return (
<FFormGroup
name={'customer_id'}
label={<T id={'customer_name'} />}
customers={customers}
labelInfo={<FieldRequiredHint />}
inline={true}
fastField={true}
shouldUpdate={customerNameFieldShouldUpdate}
>
<CustomersSelect
name={'customer_id'}
items={customers}
placeholder={<T id={'select_customer_account'} />}
onItemChange={(customer) => {
setFieldValue('customer_id', customer.id);
setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
/>
{values.customer_id && (
<CustomerButtonLink customerId={values.customer_id}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
);
}
const CustomerButtonLink = styled(CustomerDrawerLink)`
font-size: 11px;
margin-top: 6px;

View File

@@ -11,18 +11,18 @@ import {
ControlGroup,
} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime';
import { FastField, ErrorMessage, useFormikContext } from 'formik';
import { FastField, ErrorMessage, useFormikContext, useFormik } from 'formik';
import {
FeatureCan,
FFormGroup,
FInputGroup,
FormattedMessage as T,
CustomerSelectField,
FieldRequiredHint,
Icon,
InputPrependButton,
CustomerDrawerLink,
CustomersSelect,
} from '@/components';
import {
momentFormatter,
@@ -129,41 +129,7 @@ export default function EstimateFormHeader() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}
<FastField
name={'customer_id'}
customers={customers}
shouldUpdate={customersFieldShouldUpdate}
>
{({ form, field: { value }, meta: { error, touched } }) => (
<FormGroup
label={<T id={'customer_name'} />}
inline={true}
className={classNames(CLASSES.FILL, 'form-group--customer')}
labelInfo={<FieldRequiredHint />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'customer_id'} />}
>
<CustomerSelectField
contacts={customers}
selectedContactId={value}
defaultSelectText={<T id={'select_customer_account'} />}
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
intent={inputIntent({ error, touched })}
allowCreate={true}
/>
{value && (
<CustomerButtonLink customerId={value}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FormGroup>
)}
</FastField>
<EstimateFormCustomerSelect />
{/* ----------- Exchange Rate ----------- */}
<EstimateExchangeRateInputField
@@ -264,6 +230,45 @@ export default function EstimateFormHeader() {
);
}
/**
* Customer select field of estimate form.
* @returns {React.ReactNode}
*/
function EstimateFormCustomerSelect() {
const { setFieldValue, values } = useFormikContext();
const { customers } = useEstimateFormContext();
return (
<FFormGroup
label={<T id={'customer_name'} />}
inline={true}
labelInfo={<FieldRequiredHint />}
name={'customer_id'}
customers={customers}
shouldUpdate={customersFieldShouldUpdate}
fastField={true}
>
<CustomersSelect
name={'customer_id'}
items={customers}
placeholder={<T id={'select_customer_account'} />}
onItemChange={(customer) => {
setFieldValue('customer_id', customer.id);
setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
fastField={true}
/>
{values.customer_id && (
<CustomerButtonLink customerId={values.customer_id}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
);
}
const CustomerButtonLink = styled(CustomerDrawerLink)`
font-size: 11px;
margin-top: 6px;

View File

@@ -10,7 +10,7 @@ import {
ControlGroup,
} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime';
import { FastField, ErrorMessage, useFormikContext } from 'formik';
import { FastField, ErrorMessage, useFormikContext, useFormik } from 'formik';
import * as R from 'ramda';
import {
@@ -19,12 +19,12 @@ import {
Col,
Row,
CustomerDrawerLink,
CustomerSelectField,
FieldRequiredHint,
Icon,
InputPrependButton,
FeatureCan,
FInputGroup,
CustomersSelect,
} from '@/components';
import {
momentFormatter,
@@ -134,49 +134,13 @@ InvoiceFormInvoiceNumberField.displayName = 'InvoiceFormInvoiceNumberField';
*/
export default function InvoiceFormHeaderFields() {
// Invoice form context.
const { customers, projects } = useInvoiceFormContext();
const { projects } = useInvoiceFormContext();
const { values } = useFormikContext();
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}
<FastField
name={'customer_id'}
customers={customers}
shouldUpdate={customerNameFieldShouldUpdate}
>
{({ form, field: { value }, meta: { error, touched } }) => (
<FFormGroup
name={'customer_id'}
label={<T id={'customer_name'} />}
inline={true}
className={classNames(
'form-group--customer-name',
'form-group--select-list',
CLASSES.FILL,
)}
labelInfo={<FieldRequiredHint />}
>
<CustomerSelectField
contacts={customers}
selectedContactId={value}
defaultSelectText={<T id={'select_customer_account'} />}
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
/>
{value && (
<CustomerButtonLink customerId={value}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
)}
</FastField>
<InvoiceFormCustomerSelect />
{/* ----------- Exchange rate ----------- */}
<InvoiceExchangeRateInputField
@@ -284,6 +248,44 @@ export default function InvoiceFormHeaderFields() {
);
}
/**
* Customer select field of the invoice form.
* @returns {React.ReactNode}
*/
function InvoiceFormCustomerSelect() {
const { customers } = useInvoiceFormContext();
const { values, setFieldValue } = useFormikContext();
return (
<FFormGroup
name={'customer_id'}
customers={customers}
shouldUpdate={customerNameFieldShouldUpdate}
label={<T id={'customer_name'} />}
inline={true}
labelInfo={<FieldRequiredHint />}
fastField={true}
>
<CustomersSelect
name={'customer_id'}
items={customers}
placeholder={<T id={'select_customer_account'} />}
onItemChange={(customer) => {
setFieldValue('customer_id', customer.id);
setFieldValue('currency_code', customer?.currency_code);
}}
allowCreate={true}
fastField={true}
/>
{values.customer_id && (
<CustomerButtonLink customerId={values.customer_id}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
);
}
const CustomerButtonLink = styled(CustomerDrawerLink)`
font-size: 11px;
margin-top: 6px;

View File

@@ -15,8 +15,12 @@ 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 {
CustomersSelect,
FInputGroup,
FeatureCan,
FormattedMessage as T,
} from '@/components';
import { CLASSES } from '@/constants/classes';
import {
safeSumBy,
@@ -28,7 +32,6 @@ import {
import {
FFormGroup,
AccountsSelect,
CustomerSelectField,
FieldRequiredHint,
Icon,
InputPrependButton,
@@ -143,8 +146,7 @@ const PaymentReceivePaymentNoField = R.compose(
*/
export default function PaymentReceiveHeaderFields() {
// Payment receive form context.
const { customers, accounts, projects, isNewMode } =
usePaymentReceiveFormContext();
const { accounts, projects } = usePaymentReceiveFormContext();
// Formik form context.
const {
@@ -152,8 +154,6 @@ export default function PaymentReceiveHeaderFields() {
setFieldValue,
} = useFormikContext();
const customerFieldRef = useAutofocus();
// Calculates the full-amount received.
const totalDueAmount = useMemo(
() => safeSumBy(entries, 'due_amount'),
@@ -176,45 +176,7 @@ export default function PaymentReceiveHeaderFields() {
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ------------- Customer name ------------- */}
<FastField
name={'customer_id'}
customers={customers}
shouldUpdate={customersFieldShouldUpdate}
>
{({ form, field: { value }, meta: { error, touched } }) => (
<FormGroup
label={<T id={'customer_name'} />}
inline={true}
className={classNames('form-group--select-list', CLASSES.FILL)}
labelInfo={<FieldRequiredHint />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'customer_id'} />}
>
<CustomerSelectField
contacts={customers}
selectedContactId={value}
defaultSelectText={<T id={'select_customer_account'} />}
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 && (
<CustomerButtonLink customerId={value}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FormGroup>
)}
</FastField>
<PaymentReceiveCustomerSelect />
{/* ----------- Exchange rate ----------- */}
<PaymentReceiveExchangeRateInputField
@@ -361,3 +323,47 @@ const CustomerButtonLink = styled(CustomerDrawerLink)`
font-size: 11px;
margin-top: 6px;
`;
/**
* Customer select field of payment receive form.
* @returns {React.ReactNode}
*/
function PaymentReceiveCustomerSelect() {
// Payment receive form context.
const { customers, isNewMode } = usePaymentReceiveFormContext();
// Formik form context.
const { values, setFieldValue } = useFormikContext();
return (
<FFormGroup
label={<T id={'customer_name'} />}
inline={true}
labelInfo={<FieldRequiredHint />}
name={'customer_id'}
customers={customers}
fastField={true}
shouldUpdate={customersFieldShouldUpdate}
>
<CustomersSelect
name={'customer_id'}
items={customers}
placeholder={<T id={'select_customer_account'} />}
onItemChange={(customer) => {
setFieldValue('customer_id', customer.id);
setFieldValue('full_amount', '');
setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
disabled={!isNewMode}
allowCreate={true}
fastField={true}
/>
{values.customer_id && (
<CustomerButtonLink customerId={values.customer_id}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
);
}

View File

@@ -10,7 +10,7 @@ import {
ControlGroup,
} from '@blueprintjs/core';
import { DateInput } from '@blueprintjs/datetime';
import { FastField, ErrorMessage, useFormikContext } from 'formik';
import { FastField, ErrorMessage, useFormikContext, useFormik } from 'formik';
import * as R from 'ramda';
import { CLASSES } from '@/constants/classes';
@@ -27,6 +27,7 @@ import {
FormattedMessage as T,
FeatureCan,
FInputGroup,
CustomersSelect,
} from '@/components';
import { ProjectsSelect } from '@/containers/Projects/components';
import {
@@ -130,44 +131,12 @@ const ReceiptFormReceiptNumberField = R.compose(
* Receipt form header fields.
*/
export default function ReceiptFormHeader() {
const { accounts, customers, projects } = useReceiptFormContext();
const { accounts, projects } = useReceiptFormContext();
return (
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
{/* ----------- Customer name ----------- */}
<FastField
name={'customer_id'}
customers={customers}
shouldUpdate={customersFieldShouldUpdate}
>
{({ form, field: { value }, meta: { error, touched } }) => (
<FormGroup
label={<T id={'customer_name'} />}
inline={true}
className={classNames(CLASSES.FILL, 'form-group--customer')}
labelInfo={<FieldRequiredHint />}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'customer_id'} />}
>
<CustomerSelectField
contacts={customers}
selectedContactId={value}
defaultSelectText={<T id={'select_customer_account'} />}
onContactSelected={(customer) => {
form.setFieldValue('customer_id', customer.id);
form.setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
/>
{value && (
<CustomerButtonLink customerId={value}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FormGroup>
)}
</FastField>
<ReceiptFormCustomerSelect />
{/* ----------- Exchange rate ----------- */}
<ReceiptExchangeRateInputField
@@ -264,6 +233,44 @@ export default function ReceiptFormHeader() {
);
}
/**
* Customer select field of receipt form.
* @returns {React.ReactNode}
*/
function ReceiptFormCustomerSelect() {
const { setFieldValue, values } = useFormikContext();
const { customers } = useReceiptFormContext();
return (
<FFormGroup
name={'customer_id'}
label={<T id={'customer_name'} />}
inline={true}
labelInfo={<FieldRequiredHint />}
customers={customers}
fastField={true}
shouldUpdate={customersFieldShouldUpdate}
>
<CustomersSelect
name={'customer_id'}
items={customers}
placeholder={<T id={'select_customer_account'} />}
onItemChange={(customer) => {
setFieldValue('customer_id', customer.id);
setFieldValue('currency_code', customer?.currency_code);
}}
popoverFill={true}
allowCreate={true}
/>
{values.customer_id && (
<CustomerButtonLink customerId={values.customer_id}>
<T id={'view_customer_details'} />
</CustomerButtonLink>
)}
</FFormGroup>
);
}
const CustomerButtonLink = styled(CustomerDrawerLink)`
font-size: 11px;
margin-top: 6px;