Skip to content

Commit

Permalink
Merge pull request #551 from commercelayer/feat/custom-field-error
Browse files Browse the repository at this point in the history
Add multi fields validation
  • Loading branch information
acasazza authored Jul 25, 2024
2 parents 4e0dfbe + 39ba089 commit 43405f8
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 96 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useNx": false,
"npmClient": "pnpm",
"version": "4.14.5",
"version": "4.15.0-beta.3",
"command": {
"version": {
"preid": "beta"
Expand Down
119 changes: 98 additions & 21 deletions packages/docs/stories/examples/checkout/002.addresses.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,20 +274,7 @@ export const CustomerInvertAddresses: StoryFn = (args) => {
</div>
{/* Use `key` to re-render the ShippingAddressForm once we have the order from `fetchOrder`. */}
{/* When you are in your own project, you can retrieve the order before rendering the form. */}
<ShippingAddressForm
key={shippingAddress?.id}
customFieldMessageError={(props) => {
const textWithSpace = /^[a-zA-Z0-9\s]{1,20}$/
console.log('props.value', props.value)
if (
props.field === 'shipping_address_line_1' &&
!textWithSpace.test(props.value)
) {
return 'Validation error - The address should be 1-20 characters long - this is a custom message'
}
return null
}}
>
<ShippingAddressForm key={shippingAddress?.id}>
<fieldset className='flex gap-4 w-full mb-4'>
<div className='flex-1'>
<label htmlFor='shipping_address_first_name'>
Expand Down Expand Up @@ -699,8 +686,8 @@ export const CustomErrorMessages: StoryFn = () => {
customFieldMessageError={(props) => {
const regex = /[a-zA-Z]+/g
const phoneRegex = /^\d+$/
const textWithSpace = /^[a-zA-Z0-9\s]{1,20}$/
console.log('props.value billing', props.value)
// const textWithSpace = /^[a-zA-Z0-9\s]{1,20}$/
console.log('props', props)
if (
props.field === 'billing_address_first_name' &&
!regex.test(props.value)
Expand All @@ -714,11 +701,30 @@ export const CustomErrorMessages: StoryFn = () => {
? 'Validation error - only numbers are allowed - this is a custom message'
: null
}
if (
props.field === 'billing_address_line_1' &&
!textWithSpace.test(props.value)
) {
return 'Validation error - The address should be 1-20 characters long - this is a custom message'
if (props.field === 'billing_address_country_code') {
const state = props.values?.state_code as string
console.log('state', state)
console.log('props.value', props.value)
if (
['US', 'CN', 'JP', 'AU', 'CA'].includes(props.value)
) {
return [
{
field: 'billing_address_state_code',
value: undefined,
isValid: false,
message: 'State is required for this country'
}
]
} else {
return [
{
field: 'billing_address_state_code',
value: state,
isValid: true
}
]
}
}
return null
}}
Expand Down Expand Up @@ -791,6 +797,77 @@ export const CustomErrorMessages: StoryFn = () => {
/>
</div>
</fieldset>
<fieldset className='flex gap-4 w-full mb-4'>
<div className='flex-1'>
<label htmlFor='billing_address_city'>City</label>
<AddressInput
id='billing_address_city'
name='billing_address_city'
type='text'
className={inputCss}
value={billingAddress?.city}
/>
<Errors
resource='billing_address'
field='billing_address_city'
/>
</div>

<div className='flex-1'>
<label htmlFor='billing_address_country_code'>
Country
</label>
<AddressCountrySelector
data-cy='billing_address_country_code'
name='billing_address_country_code'
className={inputCss}
placeholder={{
value: '',
label: 'Country',
disabled: true
}}
value={billingAddress?.country_code}
/>
<Errors
resource='billing_address'
field='billing_address_country_code'
/>
</div>
</fieldset>
<fieldset className='flex gap-4 w-full mb-4'>
<div className='flex-1'>
<label htmlFor='billing_address_state_code'>State</label>
<AddressStateSelector
id='billing_address_state_code'
name='billing_address_state_code'
placeholder={{
value: '',
label: 'Select a state',
disabled: true
}}
className={inputCss}
/>
<Errors
resource='billing_address'
field='billing_address_state_code'
/>
</div>

<div className='flex-1'>
<label htmlFor='billing_address_zip_code'>Zip Code</label>
<AddressInput
id='billing_address_zip_code'
name='billing_address_zip_code'
type='text'
className={inputCss}
value={billingAddress?.zip_code}
/>
<Errors
resource='billing_address'
field='billing_address_zip_code'
/>
</div>
</fieldset>
</BillingAddressForm>
</AddressesContainer>
</CustomerContainer>
Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@commercelayer/react-components",
"version": "4.14.5",
"version": "4.15.0-beta.3",
"description": "The Official Commerce Layer React Components",
"main": "lib/cjs/index.js",
"module": "lib/esm/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,27 @@ export function AddressStateSelector(props: Props): JSX.Element {
/>
) : (
<BaseInput
{...(p as any)}
name={name}
ref={
(billingAddress?.validation as any) ||
shippingAddress?.validation ||
customerAddress?.validation
}
className={classNameComputed}
required={required}
placeholder={p.placeholder?.label || ''}
defaultValue={val}
type='text'
{...(p as any)}
name={name}
ref={
(billingAddress?.validation as any) ||
shippingAddress?.validation ||
customerAddress?.validation
}
className={classNameComputed}
required={required}
placeholder={p.placeholder?.label || ''}
defaultValue={val}
type='text'
onChange={(e) => {
setVal(e.target.value)
if (billingAddress.setValue != null) {
billingAddress.setValue(name, e.target.value)
}
if (shippingAddress.setValue != null) {
shippingAddress.setValue(name, e.target.value)
}
}}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,53 @@ export function BillingAddressForm(props: Props): JSX.Element {
fieldName != null &&
value != null
) {
values[fieldName.replace('shipping_address_', '')] = value
const customMessage = customFieldMessageError({
field: fieldName,
value
value,
values
})
if (customMessage != null) {
if (inError) {
const errorMsg = errors[fieldName]?.message
if (errorMsg != null && errorMsg !== customMessage) {
// @ts-expect-error no type
errors[fieldName].message = customMessage
if (typeof customMessage === 'string') {
if (inError) {
const errorMsg = errors[fieldName]?.message
if (errorMsg != null && errorMsg !== customMessage) {
// @ts-expect-error no type
errors[fieldName].message = customMessage
}
} else {
setErrorForm({
name: fieldName,
code: 'VALIDATION_ERROR',
message: customMessage
})
}
} else {
setErrorForm({
name: fieldName,
code: 'VALIDATION_ERROR',
message: customMessage
const elements = customMessage
elements.forEach((element) => {
const { field, value, isValid, message } = element
const fieldInError = errors[field] != null
if (!isValid) {
if (fieldInError) {
const errorMsg = errors[field]?.message
if (errorMsg != null && errorMsg !== message) {
// @ts-expect-error no type
errors[field].message = message
setValueForm(field, value ?? '')
}
} else {
setErrorForm({
name: field,
code: 'VALIDATION_ERROR',
message: message
})
}
} else {
if (fieldInError) {
delete errors[field]
setValueForm(field, value ?? '')
}
}
})
}
}
Expand All @@ -119,26 +150,12 @@ export function BillingAddressForm(props: Props): JSX.Element {
for (const fieldName in errors) {
const code = errors[fieldName]?.code
const message = errors[fieldName]?.message
if (['billing_address_state_code'].includes(fieldName)) {
if (!values?.['state_code']) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete errors[fieldName]
} else {
formErrors.push({
code: code as CodeErrorType,
message: message || '',
resource: 'billing_address',
field: fieldName
})
}
} else {
formErrors.push({
code: code as CodeErrorType,
message: message ?? '',
resource: 'billing_address',
field: fieldName
})
}
formErrors.push({
code: code as CodeErrorType,
message: message ?? '',
resource: 'billing_address',
field: fieldName
})
}
setAddressErrors(formErrors, 'billing_address')
} else if (values && Object.keys(values).length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,53 @@ export function ShippingAddressForm(props: Props): JSX.Element {
fieldName != null &&
value != null
) {
values[fieldName.replace('shipping_address_', '')] = value
const customMessage = customFieldMessageError({
field: fieldName,
value
value,
values
})
if (customMessage != null) {
if (inError) {
const errorMsg = errors[fieldName]?.message
if (errorMsg != null && errorMsg !== customMessage) {
// @ts-expect-error no type
errors[fieldName].message = customMessage
if (typeof customMessage === 'string') {
if (inError) {
const errorMsg = errors[fieldName]?.message
if (errorMsg != null && errorMsg !== customMessage) {
// @ts-expect-error no type
errors[fieldName].message = customMessage
}
} else {
setErrorForm({
name: fieldName,
code: 'VALIDATION_ERROR',
message: customMessage
})
}
} else {
setErrorForm({
name: fieldName,
code: 'VALIDATION_ERROR',
message: customMessage
const elements = customMessage
elements.forEach((element) => {
const { field, value, isValid, message } = element
const fieldInError = errors[field] != null
if (!isValid) {
if (fieldInError) {
const errorMsg = errors[field]?.message
if (errorMsg != null && errorMsg !== message) {
// @ts-expect-error no type
errors[field].message = message
setValueForm(field, value ?? '')
}
} else {
setErrorForm({
name: field,
code: 'VALIDATION_ERROR',
message: message
})
}
} else {
if (fieldInError) {
delete errors[field]
setValueForm(field, value ?? '')
}
}
})
}
}
Expand All @@ -118,26 +149,12 @@ export function ShippingAddressForm(props: Props): JSX.Element {
for (const fieldName in errors) {
const code = errors[fieldName]?.code
const message = errors[fieldName]?.message
if (['shipping_address_state_code'].includes(fieldName)) {
if (!values['state_code']) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete errors[fieldName]
} else {
formErrors.push({
code: code as CodeErrorType,
message: message || '',
resource: 'shipping_address',
field: fieldName
})
}
} else {
formErrors.push({
code: code as CodeErrorType,
message: message ?? '',
resource: 'shipping_address',
field: fieldName
})
}
formErrors.push({
code: code as CodeErrorType,
message: message ?? '',
resource: 'shipping_address',
field: fieldName
})
}
if (shipToDifferentAddress || invertAddresses) {
setAddressErrors(formErrors, 'shipping_address')
Expand Down
Loading

0 comments on commit 43405f8

Please sign in to comment.