Skip to content

Commit

Permalink
#375 initialization values are prepared from address field config; im…
Browse files Browse the repository at this point in the history
…provements in validation rules preparation
  • Loading branch information
rajeev-k-tomy committed Oct 20, 2024
1 parent 10b90fb commit a397e63
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 281 deletions.
Original file line number Diff line number Diff line change
@@ -1,37 +1,7 @@
import {
ConfigMultiline,
ConfigTextInput,
ConfigSelectInput,
} from '../../common/Form';
import { _objToArray } from '../../../utils';
import { createFieldConfig } from '../../../utils/field';
import RegionRenderer from '../components/RegionRenderer';
import CountryRenderer from '../components/CountryRenderer';
import { FieldConfig } from '../../../utils/field';
import { getAddressConfigByFormId } from '../../../utils/address';

function getAddressFieldRendererComponent(field) {
if (field.code === 'country_id') {
return CountryRenderer;
}

if (field.code === 'region') {
return RegionRenderer;
}

if (field.type === 'text') {
return ConfigTextInput;
}

if (field.type === 'select') {
return ConfigSelectInput;
}

if (field.type === 'multiline') {
return ConfigMultiline;
}

return null;
}
import { addressFieldRenderer } from '../../../fieldRenderers/renderers';

export default function useAddressFieldRenderer(addressFormId) {
const addressTypeConfig = getAddressConfigByFormId(addressFormId);
Expand All @@ -40,8 +10,8 @@ export default function useAddressFieldRenderer(addressFormId) {
const addressFields = _objToArray(addressTypeConfig)
.sort((field1, field2) => field1.sortOrder - field2.sortOrder)
.map((field) => ({
config: createFieldConfig(field, addressFormId),
FieldRenderer: getAddressFieldRendererComponent(field),
config: FieldConfig.create(field, addressFormId),
FieldRenderer: addressFieldRenderer.getRendererForField(field),
}))
.filter((field) => !!field.FieldRenderer);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import React from 'react';

import { SaveButton } from '../../address';
import TextInput from '../../common/Form/TextInput';
import SelectInput from '../../common/Form/SelectInput';
import CancelButton from './billingAddressForm/CancelButton';
import SaveInBookCheckbox from '../../address/components/SaveInBookCheckbox';
import { __ } from '../../../i18n';
import { _keys } from '../../../utils';
import LocalStorage from '../../../utils/localStorage';
import { useAddressFieldRenderer } from '../../address/hooks';
import { isValidCustomerAddressId } from '../../../utils/address';
import useCountryState from '../../address/hooks/useCountryState';
import useAddressWrapper from '../../address/hooks/useAddressWrapper';
import useBillingAddressAppContext from '../hooks/useBillingAddressAppContext';
import useFormValidateThenSubmit from '../../../hook/useFormValidateThenSubmit';
Expand All @@ -25,26 +22,22 @@ function BillingAddressForm() {
handleKeyDown,
billingValues,
isBillingSame,
setFieldValue,
setIsNewAddress,
selectedAddress,
setFieldTouched,
validationSchema,
setSelectedAddress,
} = useBillingAddressFormikContext();
const { isLoggedIn } = useBillingAddressAppContext();
const { reCalculateMostRecentAddressOptions } = useAddressWrapper();
const addressFields = useAddressFieldRenderer(formikData.formSectionId);
const formSubmitHandler = useFormValidateThenSubmit({
formId,
formikData,
submitHandler,
validationSchema,
});
const { countryOptions, stateOptions, hasStateOptions } = useCountryState({
fields,
formikData,
});
const { selectedCountry, isBillingAddressTouched } = formikData;

const { isBillingAddressTouched } = formikData;

const saveAddressAction = async () => {
let newAddressId = selectedAddress;
Expand Down Expand Up @@ -82,93 +75,21 @@ function BillingAddressForm() {
reCalculateMostRecentAddressOptions();
};

const handleCountryChange = (event) => {
const newValue = event.target.value;
setFieldTouched(fields.country, newValue);
setFieldValue(fields.country, newValue);
// when country is changed, then always reset region field.
setFieldValue(fields.region, '');
};

if (viewMode) {
return null;
}

return (
<>
<div className="py-2">
<TextInput
required
label={__('Company')}
name={fields.company}
formikData={formikData}
onKeyDown={handleKeyDown}
placeholder={__('Company')}
/>
<TextInput
required
name={fields.firstname}
formikData={formikData}
label={__('First name')}
onKeyDown={handleKeyDown}
placeholder={__('First name')}
/>
<TextInput
required
name={fields.lastname}
label={__('Last name')}
formikData={formikData}
onKeyDown={handleKeyDown}
placeholder={__('Last name')}
/>
<TextInput
required
label={__('Street')}
formikData={formikData}
onKeyDown={handleKeyDown}
placeholder={__('Street')}
name={`${fields.street}[0]`}
/>
<TextInput
required
placeholder="12345"
name={fields.zipcode}
formikData={formikData}
label={__('Postal Code')}
onKeyDown={handleKeyDown}
/>
<TextInput
required
label={__('City')}
name={fields.city}
formikData={formikData}
placeholder={__('City')}
onKeyDown={handleKeyDown}
/>
<SelectInput
required
label={__('Country')}
name={fields.country}
formikData={formikData}
options={countryOptions}
onChange={handleCountryChange}
/>
<SelectInput
required
label={__('State')}
name={fields.region}
options={stateOptions}
formikData={formikData}
isHidden={!selectedCountry || !hasStateOptions}
/>
<TextInput
required
label={__('Phone')}
name={fields.phone}
formikData={formikData}
onKeyDown={handleKeyDown}
placeholder={__('+32 000 000 000')}
/>
{addressFields.map(({ FieldRenderer, config }) => (
<FieldRenderer
config={config}
key={config.code}
formikData={formikData}
onKeyDown={handleKeyDown}
/>
))}
<SaveInBookCheckbox fields={fields} formikData={formikData} />
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import useCheckoutFormContext from '../../../hook/useCheckoutFormContext';
import BillingAddressFormContext from '../context/BillingAddressFormikContext';

const initialValidationSchema = {
...addressInitialValidationSchema,
...addressInitialValidationSchema(BILLING_ADDR_FORM),
// Here you can add your initial validation schema modifications
};

Expand Down
14 changes: 4 additions & 10 deletions src/reactapp/src/components/billingAddress/utility/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { __ } from '../../../i18n';
import { _isObjEmpty } from '../../../utils';
import { BILLING_ADDR_FORM } from '../../../config';
import LocalStorage from '../../../utils/localStorage';
import { initialCountry } from '../../../utils/address';
import { addressInitValues, initialCountry } from '../../../utils/address';

export const CART_BILLING_ADDRESS = 'cart_billing_address';
export const billingAddrOtherOptionField =
'additional.billing_address_selected_other_option';

export const billingAddressFormInitValues = {
company: '',
firstname: '',
lastname: '',
street: [''],
phone: '',
zipcode: '',
city: '',
region: '',
country: initialCountry,
...addressInitValues(BILLING_ADDR_FORM),
country_id: initialCountry,
isSameAsShipping: LocalStorage.getBillingSameAsShippingInfo(),
saveInBook: false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function ConfigMultiline({ formikData, config, ...rest }) {
<div className={classNames('mt-2 form-control', wrapperClasses)}>
<div className="flex items-center justify-between">
{label && label[0] && (
<label htmlFor={inputId} className="md:text-sm">
<label htmlFor={`${inputId}-0`} className="md:text-sm">
{label[0]}
{isRequired && <sup> *</sup>}
</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { node } from 'prop-types';

import {
initialCountry,
addressInitValues,
isCartAddressValid,
CART_SHIPPING_ADDRESS,
isValidCustomerAddressId,
initialAddressValidationShemaFromFieldConfig,
addressInitialValidationSchema,
} from '../../../utils/address';
import {
useShippingAddressAppContext,
Expand All @@ -30,20 +31,13 @@ import useCheckoutFormContext from '../../../hook/useCheckoutFormContext';
import ShippingAddressFormContext from '../context/ShippingAddressFormikContext';

const defaultValues = {
company: '',
firstname: '',
lastname: '',
street: [''],
phone: '',
zipcode: '',
city: '',
region: '',
...addressInitValues(SHIPPING_ADDR_FORM),
country_id: initialCountry,
saveInBook: false,
};

const initialValidationSchema = {
...initialAddressValidationShemaFromFieldConfig(SHIPPING_ADDR_FORM),
...addressInitialValidationSchema(SHIPPING_ADDR_FORM),
// Here you can add your initial validation schema modifications
};

Expand Down
53 changes: 53 additions & 0 deletions src/reactapp/src/fieldRenderers/renderers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
ConfigMultiline,
ConfigTextInput,
ConfigSelectInput,
} from '../components/common/Form';
import { _emptyFunc } from '../utils';
import { FieldType } from '../utils/field';
import RegionRenderer from '../components/address/components/RegionRenderer';
import CountryRenderer from '../components/address/components/CountryRenderer';

class FieldRenderer {
rendererList = [];

constructor() {
this.#registerDefaultRenderers();
}

register(renderer, sortOrder = 100, conditionCallback = _emptyFunc()) {
const newRenderer = {
renderer,
sortOrder,
canRenderField: conditionCallback,
};
this.rendererList = [...this.rendererList, newRenderer].sort(
(renderer1, renderer2) => renderer1.sortOrder - renderer2.sortOrder
);
}

getRendererForField(field) {
// eslint-disable-next-line no-restricted-syntax
for (const renderer of this.rendererList) {
if (renderer.canRenderField(field)) {
return renderer.renderer;
}
}

return false;
}

#registerDefaultRenderers() {
this.register(CountryRenderer, 10, (field) => field.code === 'country_id');
this.register(RegionRenderer, 20, (field) => field.code === 'region');
this.register(ConfigTextInput, 30, (field) => FieldType.isText(field.type));
this.register(ConfigSelectInput, 10, (field) =>
FieldType.isSelect(field.type)
);
this.register(ConfigMultiline, 10, (field) =>
FieldType.isMultiline(field.type)
);
}
}

export const addressFieldRenderer = new FieldRenderer();
Loading

0 comments on commit a397e63

Please sign in to comment.