1
0
This commit is contained in:
Ahmed Bouhuolia
2026-03-27 13:14:54 +02:00
parent d5cc3d1a71
commit 4dc5c5abe0
17 changed files with 107 additions and 218 deletions
@@ -28,6 +28,7 @@ export function SalutationList({ ...restProps }: SalutationListProps) {
items={items}
valueAccessor={'key'}
textAccessor={'label'}
labelAccessor={'_label'}
placeholder={intl.get('salutation')}
filterable={false}
{...restProps}
@@ -22,18 +22,13 @@ export function CustomerFloatingActions() {
};
// Formik context.
const { resetForm, submitForm, isSubmitting } = useFormikContext();
const { submitForm, isSubmitting } = useFormikContext();
// Handle submit button click.
const handleSubmitBtnClick = (_event: React.MouseEvent<HTMLElement>) => {
setSubmitPayload({ noRedirect: false });
};
// handle clear button clicl.
const handleClearBtnClick = (_event: React.MouseEvent<HTMLElement>) => {
resetForm();
};
// Handle submit & new button click.
const handleSubmitAndNewClick = (_event: React.MouseEvent<HTMLElement>) => {
submitForm();
@@ -44,7 +39,7 @@ export function CustomerFloatingActions() {
<FloatingActionsGroup spacing={10}>
<ButtonGroup>
{/* ----------- Save and New ----------- */}
<SaveButton
<Button
disabled={isSubmitting}
loading={isSubmitting}
intent={Intent.PRIMARY}
@@ -61,9 +56,9 @@ export function CustomerFloatingActions() {
/>
</Menu>
}
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
position={Position.BOTTOM_RIGHT}
minimal
>
<Button
disabled={isSubmitting}
@@ -72,27 +67,16 @@ export function CustomerFloatingActions() {
/>
</Popover>
</ButtonGroup>
{/* ----------- Clear & Reset----------- */}
<Button
className={'ml1'}
disabled={isSubmitting}
onClick={handleClearBtnClick}
text={!isNewMode ? <T id={'reset'} /> : <T id={'clear'} />}
/>
</FloatingActionsGroup>
);
}
const FloatingActionsGroup = styled(Group)`
padding: 12px 0;
padding: 10px 0;
padding-left: 165px;
border-top: 1px solid #50555a;
position: sticky;
bottom: 0;
background: var(--color-card-background);
`;
const SaveButton = styled(Button)`
min-width: 80px;
z-index: 1;
`;
@@ -25,11 +25,10 @@ export function CustomerFormContent() {
<Card className={css`padding-bottom: 0 !important;`}>
<Group verticalAlign={'top'} alignItems={'flex-start'} flexWrap={'nowrap'}>
<Tabs
vertical
large
selectedTabId={selectedTabId}
onChange={handleTabChange}
className={css`position: sticky; top: 20px; .bp4-large > .bp4-tab{font-size: 14px;} `}
className={css`position: sticky; top: 20px;`}
vertical
>
<Tab id={'primary'} title={'Basic'} />
<Tab id={'financial'} title={'Financial'} />
@@ -12,6 +12,7 @@ import {
FMoneyInputGroup,
ExchangeRateInputGroup,
FDateInput,
Icon,
Box,
} from '@/components';
import { useCustomerFormContext } from './CustomerFormProvider';
@@ -58,12 +59,12 @@ export function CustomerFormFinancialSection() {
label={<T id={'customer.label.opening_branch'} />}
name={'opening_balance_branch_id'}
inline
fill
>
<BranchSelect
name={'opening_balance_branch_id'}
branches={branches}
popoverProps={{ minimal: true }}
fastField
/>
</FFormGroup>
</FeatureCan>
@@ -95,6 +96,9 @@ function CustomerOpeningBalanceAtField() {
disabled={customerId}
formatDate={(date) => date.toLocaleDateString()}
parseDate={(str) => new Date(str)}
inputProps={{
leftIcon: <Icon icon={'date-range'} />,
}}
fill={true}
/>
</FFormGroup>
@@ -118,7 +122,7 @@ function CustomerOpeningBalanceField() {
fastField={true}
fill
>
<ControlGroup fill>
<ControlGroup>
<InputPrependText text={values.currency_code as string} />
<FMoneyInputGroup
name={'opening_balance'}
@@ -166,6 +166,9 @@ const CustomerFormFields = styled.div`
.bp6-form-content {
min-width: 300px;
}
.bp4-form-group{
margin-bottom: 20px;
}
.bp4-form-group.bp4-inline label.bp4-label {
min-width: 140px;
}
@@ -19,8 +19,9 @@ export function VendorBillingAddress() {
label={<T id={'country'} />}
inline
fill
fastField
>
<FInputGroup name={'billing_address_country'} fill />
<FInputGroup name={'billing_address_country'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -28,8 +29,9 @@ export function VendorBillingAddress() {
label={<T id={'address_line_1'} />}
inline
fill
fastField
>
<FTextArea name={'billing_address1'} fill />
<FTextArea name={'billing_address1'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -37,8 +39,9 @@ export function VendorBillingAddress() {
label={<T id={'address_line_2'} />}
inline
fill
fastField
>
<FTextArea name={'billing_address2'} fill />
<FTextArea name={'billing_address2'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -46,8 +49,9 @@ export function VendorBillingAddress() {
label={<T id={'city_town'} />}
inline
fill
fastField
>
<FInputGroup name={'billing_address_city'} fill />
<FInputGroup name={'billing_address_city'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -55,8 +59,9 @@ export function VendorBillingAddress() {
label={<T id={'state'} />}
inline
fill
fastField
>
<FInputGroup name={'billing_address_state'} fill />
<FInputGroup name={'billing_address_state'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -64,8 +69,9 @@ export function VendorBillingAddress() {
label={<T id={'zip_code'} />}
inline
fill
fastField
>
<FInputGroup name={'billing_address_postcode'} fill />
<FInputGroup name={'billing_address_postcode'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -73,8 +79,9 @@ export function VendorBillingAddress() {
label={<T id={'phone'} />}
inline
fill
fastField
>
<FInputGroup name={'billing_address_phone'} fill />
<FInputGroup name={'billing_address_phone'} fill fastField />
</FFormGroup>
</Box>
);
@@ -44,10 +44,12 @@ export function VendorFinanicalPanelTab() {
label={<T id={'currency'} />}
fastField
inline
fastField
>
<CurrencySelectList
name="currency_code"
items={currencies}
fastField
/>
</FFormGroup>
@@ -93,16 +95,17 @@ function VendorOpeningBalanceField() {
<FFormGroup
name={'opening_balance'}
label={<T id={'opening_balance'} />}
inline={true}
shouldUpdate={openingBalanceFieldShouldUpdate}
shouldUpdateDeps={{ currencyCode: values.currency_code }}
fastField={true}
inline
fastField
>
<ControlGroup>
<InputPrependText text={values.currency_code} />
<FMoneyInputGroup
name={'opening_balance'}
inputGroupProps={{ fill: true }}
fastField
/>
</ControlGroup>
</FFormGroup>
@@ -123,8 +126,9 @@ function VendorOpeningBalanceAtField() {
<FFormGroup
name={'opening_balance_at'}
label={<T id={'opening_balance_at'} />}
inline={true}
helperText={<ErrorMessage name="opening_balance_at" />}
inline
fastField
>
<FDateInput
name={'opening_balance_at'}
@@ -132,7 +136,8 @@ function VendorOpeningBalanceAtField() {
disabled={vendorId}
formatDate={(date) => date.toLocaleDateString()}
parseDate={(str) => new Date(str)}
fill={true}
fill
fastField
/>
</FFormGroup>
);
@@ -156,12 +161,14 @@ function VendorOpeningBalanceExchangeRateField() {
<FFormGroup
label={' '}
name={'opening_balance_exchange_rate'}
inline={true}
inline
fastField
>
<ExchangeRateInputGroup
fromCurrency={values.currency_code}
toCurrency={currentOrganization.base_currency}
name={'opening_balance_exchange_rate'}
fastField
/>
</FFormGroup>
);
@@ -20,7 +20,7 @@ import { useVendorFormContext } from './VendorFormProvider';
*/
export function VendorFloatingActions() {
// Formik context.
const { resetForm, isSubmitting, submitForm } = useFormikContext();
const { isSubmitting, submitForm } = useFormikContext();
// Vendor form context.
const { isNewMode, setSubmitPayload } = useVendorFormContext();
@@ -36,16 +36,11 @@ export function VendorFloatingActions() {
setSubmitPayload({ noRedirect: true });
};
// Handle clear button click.
const handleClearBtnClick = () => {
resetForm();
};
return (
<FloatingActionsGroup spacing={10}>
<ButtonGroup>
{/* ----------- Save and New ----------- */}
<SaveButton
<Button
disabled={isSubmitting}
loading={isSubmitting}
intent={Intent.PRIMARY}
@@ -62,9 +57,9 @@ export function VendorFloatingActions() {
/>
</Menu>
}
minimal={true}
interactionKind={PopoverInteractionKind.CLICK}
position={Position.BOTTOM_LEFT}
position={Position.BOTTOM_RIGHT}
minimal
>
<Button
disabled={isSubmitting}
@@ -73,26 +68,16 @@ export function VendorFloatingActions() {
/>
</Popover>
</ButtonGroup>
{/* ----------- Clear & Reset----------- */}
<Button
className={'ml1'}
disabled={isSubmitting}
onClick={handleClearBtnClick}
text={!isNewMode ? <T id={'reset'} /> : <T id={'clear'} />}
/>
</FloatingActionsGroup>
);
}
const FloatingActionsGroup = styled(Group)`
padding: 12px 0;
padding: 10px 0;
padding-left: 165px;
border-top: 1px solid #50555a;
position: sticky;
bottom: 0;
background: var(--color-card-background);
`;
const SaveButton = styled(Button)`
min-width: 80px;
z-index: 1;
`;
@@ -2,21 +2,22 @@
import React from 'react';
import intl from 'react-intl-universal';
import { ControlGroup } from '@blueprintjs/core';
import { FormattedMessage as T, FFormGroup, FInputGroup } from '@/components';
import { FormattedMessage as T, FFormGroup, FInputGroup, Box } from '@/components';
/**
* Vendor form after primary section.
*/
export function VendorFormAfterPrimarySection() {
return (
<div className={'customer-form__after-primary-section-content'}>
<Box>
{/*------------ Vendor email -----------*/}
<FFormGroup
name={'email'}
label={<T id={'vendor_email'} />}
inline={true}
inline
fastField
>
<FInputGroup name={'email'} />
<FInputGroup name={'email'} fastField />
</FFormGroup>
{/*------------ Phone number -----------*/}
@@ -24,21 +25,23 @@ export function VendorFormAfterPrimarySection() {
name={'work_phone'}
className={'form-group--phone-number'}
label={<T id={'phone_number'} />}
inline={true}
inline
fastField
>
<ControlGroup>
<FInputGroup name={'work_phone'} placeholder={intl.get('work')} />
<FInputGroup name={'work_phone'} placeholder={intl.get('work')} fastField />
<FInputGroup
name={'personal_phone'}
placeholder={intl.get('mobile')}
fastField
/>
</ControlGroup>
</FFormGroup>
{/*------------ Vendor website -----------*/}
<FFormGroup name={'website'} label={<T id={'website'} />} inline={true}>
<FInputGroup name={'website'} placeholder={'http://'} />
<FFormGroup name={'website'} label={<T id={'website'} />} inline fastField>
<FInputGroup name={'website'} placeholder={'http://'} fastField />
</FFormGroup>
</div>
</Box>
);
}
@@ -29,22 +29,26 @@ export function VendorFormBasicSection({}) {
label={<T id={'contact_name'} />}
inline
fill
fastField
>
<ControlGroup fill>
<SalutationList
name={'salutation'}
popoverProps={{ minimal: true }}
fastField
/>
<FInputGroup
name={'first_name'}
placeholder={intl.get('first_name')}
inputRef={(ref) => (firstNameFieldRef.current = ref)}
fill
fastField
/>
<FInputGroup
name={'last_name'}
placeholder={intl.get('last_name')}
fill
fastField
/>
</ControlGroup>
</FFormGroup>
@@ -55,10 +59,9 @@ export function VendorFormBasicSection({}) {
helperText="Add a unique account number to identify, reference and search for the contact."
inline
fill
fastField
>
<FInputGroup
name={'vendor_code'}
fill />
<FInputGroup name={'vendor_code'} fill fastField />
</FFormGroup>
{/*----------- Company Name -----------*/}
@@ -67,8 +70,9 @@ export function VendorFormBasicSection({}) {
label={<T id={'company_name'} />}
inline
fill
fastField
>
<FInputGroup name={'company_name'} fill />
<FInputGroup name={'company_name'} fill fastField />
</FFormGroup>
{/*----------- Display Name -----------*/}
@@ -78,11 +82,13 @@ export function VendorFormBasicSection({}) {
helperText="This is the name that appears on invoices and emails."
inline
fill
fastField
>
<DisplayNameList
name={'display_name'}
popoverProps={{ minimal: true }}
buttonProps={{ fill: true }}
fastField
/>
</FFormGroup>
@@ -93,10 +99,12 @@ export function VendorFormBasicSection({}) {
name={'email'}
label={<T id={'vendor_email'} />}
inline
fastField
>
<FInputGroup
name={'email'}
leftIcon={<Icon icon="envelope" />}
fastField
/>
</FFormGroup>
@@ -106,26 +114,26 @@ export function VendorFormBasicSection({}) {
className={'form-group--phone-number'}
label={<T id={'phone_number'} />}
inline
fastField
>
<Stack spacing={10}>
<FInputGroup
name={'work_phone'}
placeholder={intl.get('work')}
leftIcon="phone"
<FInputGroup name={'work_phone'} placeholder={intl.get('work')} leftIcon="phone" fastField
/>
<FInputGroup
name={'personal_phone'}
placeholder={intl.get('mobile')}
fastField
/>
</Stack>
</FFormGroup>
{/*------------ Vendor website -----------*/}
<FFormGroup name={'website'} label={<T id={'website'} />} inline>
<FFormGroup name={'website'} label={<T id={'website'} />} inline fastField>
<FInputGroup
name={'website'}
placeholder={'http://'}
leftIcon={<BlueprintIcon icon="globe-network" />}
fastField
/>
</FFormGroup>
</Box>
@@ -26,11 +26,10 @@ export function VendorFormContent() {
<Card className={css`padding-bottom: 0 !important;`}>
<Group verticalAlign={'top'} alignItems={'flex-start'} flexWrap={'nowrap'}>
<Tabs
vertical
large
selectedTabId={selectedTabId}
onChange={handleTabChange}
className={css`position: sticky; top: 20px; .bp4-large > .bp4-tab{font-size: 14px;} `}
className={css`position: sticky; top: 20px;`}
vertical
>
<Tab id={'primary'} title={'Basic'} />
<Tab id={'financial'} title={'Financial'} />
@@ -12,6 +12,7 @@ import {
FMoneyInputGroup,
ExchangeRateInputGroup,
FDateInput,
Icon,
Box,
} from '@/components';
import { useVendorFormContext } from './VendorFormProvider';
@@ -46,6 +47,7 @@ export function VendorFormFinancialSection() {
name="currency_code"
items={currencies}
disabled={vendorId}
fastField
/>
</FFormGroup>
@@ -95,6 +97,9 @@ function VendorOpeningBalanceAtField() {
disabled={vendorId}
formatDate={(date) => date.toLocaleDateString()}
parseDate={(str) => new Date(str)}
inputProps={{
leftIcon: <Icon icon={'date-range'} />,
}}
fill={true}
/>
</FFormGroup>
@@ -120,7 +120,9 @@ const VendorFormFields = styled.div`
.bp6-form-content {
min-width: 300px;
}
.bp4-form-group{
margin-bottom: 20px;
}
.bp4-form-group.bp4-inline label.bp4-label {
min-width: 140px;
}
@@ -9,8 +9,8 @@ export function VendorFormNotesSection() {
<T id={'notes'} />
</VendorFormSectionTitle>
<FFormGroup name={'note'} label={<T id={'note'} />} inline fill>
<FTextArea name={'note'} fill />
<FFormGroup name={'note'} label={<T id={'note'} />} inline fill fastField>
<FTextArea name={'note'} fill fastField />
</FFormGroup>
</Box>
);
@@ -1,82 +0,0 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import classNames from 'classnames';
import { ControlGroup } from '@blueprintjs/core';
import {
FormattedMessage as T,
FFormGroup,
FInputGroup,
Hint,
FieldRequiredHint,
SalutationList,
DisplayNameList,
} from '@/components';
import { CLASSES } from '@/constants/classes';
import { useAutofocus } from '@/hooks';
/**
* Vendor form primary section.
*/
export function VendorFormPrimarySection() {
const firstNameFieldRef = useAutofocus();
return (
<div className={'customer-form__primary-section-content'}>
{/**----------- Vendor name -----------*/}
<FFormGroup
name={'salutation'}
className={classNames('form-group--contact_name')}
label={<T id={'contact_name'} />}
inline={true}
>
<ControlGroup>
<SalutationList
name={'salutation'}
popoverProps={{ minimal: true }}
/>
<FInputGroup
name={'first_name'}
placeholder={intl.get('first_name')}
className={classNames('input-group--first-name')}
inputRef={(ref) => (firstNameFieldRef.current = ref)}
/>
<FInputGroup
name={'last_name'}
placeholder={intl.get('last_name')}
className={classNames('input-group--last-name')}
/>
</ControlGroup>
</FFormGroup>
{/*----------- Company Name -----------*/}
<FFormGroup
name={'company_name'}
className={classNames('form-group--company_name')}
label={<T id={'company_name'} />}
inline={true}
>
<FInputGroup name={'company_name'} />
</FFormGroup>
{/*----------- Display Name -----------*/}
<FFormGroup
name={'display_name'}
label={
<>
<T id={'display_name'} />
<FieldRequiredHint />
<Hint />
</>
}
fastField
inline
>
<DisplayNameList
name={'display_name'}
popoverProps={{ minimal: true }}
/>
</FFormGroup>
</div>
);
}
@@ -19,8 +19,9 @@ export function VendorShippingAddress() {
label={<T id={'country'} />}
inline
fill
fastField
>
<FInputGroup name={'shipping_address_country'} fill />
<FInputGroup name={'shipping_address_country'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -28,8 +29,9 @@ export function VendorShippingAddress() {
label={<T id={'address_line_1'} />}
inline
fill
fastField
>
<FTextArea name={'shipping_address1'} fill />
<FTextArea name={'shipping_address1'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -37,8 +39,9 @@ export function VendorShippingAddress() {
label={<T id={'address_line_2'} />}
inline
fill
fastField
>
<FTextArea name={'shipping_address2'} fill />
<FTextArea name={'shipping_address2'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -46,8 +49,9 @@ export function VendorShippingAddress() {
label={<T id={'city_town'} />}
inline
fill
fastField
>
<FInputGroup name={'shipping_address_city'} fill />
<FInputGroup name={'shipping_address_city'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -55,8 +59,9 @@ export function VendorShippingAddress() {
label={<T id={'state'} />}
inline
fill
fastField
>
<FInputGroup name={'shipping_address_state'} fill />
<FInputGroup name={'shipping_address_state'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -64,8 +69,9 @@ export function VendorShippingAddress() {
label={<T id={'zip_code'} />}
inline
fill
fastField
>
<FInputGroup name={'shipping_address_postcode'} fill />
<FInputGroup name={'shipping_address_postcode'} fill fastField />
</FFormGroup>
<FFormGroup
@@ -73,8 +79,9 @@ export function VendorShippingAddress() {
label={<T id={'phone'} />}
inline
fill
fastField
>
<FInputGroup name={'shipping_address_phone'} fill />
<FInputGroup name={'shipping_address_phone'} fill fastField />
</FFormGroup>
</Box>
);
@@ -1,43 +0,0 @@
// @ts-nocheck
import React from 'react';
import intl from 'react-intl-universal';
import classNames from 'classnames';
import { Tabs, Tab } from '@blueprintjs/core';
import { CLASSES } from '@/constants/classes';
import { VendorFinanicalPanelTab } from './VendorFinanicalPanelTab';
import CustomerAddressTabs from '@/containers/Customers/CustomerForm/CustomerAddressTabs';
import CustomerNotePanel from '@/containers/Customers/CustomerForm/CustomerNotePanel';
/**
* Vendor form tabs.
*/
export function VendorsTabs() {
return (
<div className={classNames(CLASSES.PAGE_FORM_TABS)}>
<Tabs
animate={true}
id={'vendor-tabs'}
large={true}
defaultSelectedTabId="financial"
>
<Tab
id={'financial'}
title={intl.get('financial_details')}
panel={<VendorFinanicalPanelTab />}
/>
<Tab
id={'address'}
title={intl.get('address')}
panel={<CustomerAddressTabs />}
/>
<Tab
id="notes"
title={intl.get('notes')}
panel={<CustomerNotePanel />}
/>
</Tabs>
</div>
);
}