diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f80e12..0bc0e318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added +- implemented autoUpperCase rule for countries with alphanumeric postal codes, ensuring consistent uppercase formatting. + ## [3.36.5] - 2024-07-02 ### Fixed diff --git a/react/AddressContainer.js b/react/AddressContainer.js index a0a6e2a5..436cc407 100644 --- a/react/AddressContainer.js +++ b/react/AddressContainer.js @@ -75,6 +75,11 @@ class AddressContainer extends Component { rules.fields && rules.fields.find((field) => field.name === 'postalCode') + // Convert postal code to uppercase if autoUpperCase is true + if (postalCodeField && postalCodeField.autoUpperCase) { + changedAddressFields.postalCode.value = changedAddressFields.postalCode.value.toUpperCase() + } + const diffFromPrev = address.postalCode.value !== validatedAddress.postalCode.value diff --git a/react/country/GBR.ts b/react/country/GBR.ts index edf9b0bb..1f8d220d 100644 --- a/react/country/GBR.ts +++ b/react/country/GBR.ts @@ -23,6 +23,7 @@ const rules: PostalCodeRules = { postalCodeAPI: false, size: 'small', autoComplete: 'nope', + autoUpperCase: true, }, { name: 'street', @@ -128,10 +129,7 @@ const rules: PostalCodeRules = { state: { valueIn: 'long_name', - types: [ - 'postal_town', - 'administrative_area_level_1' - ], + types: ['postal_town', 'administrative_area_level_1'], }, city: { diff --git a/react/country/GIB.ts b/react/country/GIB.ts new file mode 100644 index 00000000..1946301a --- /dev/null +++ b/react/country/GIB.ts @@ -0,0 +1,159 @@ +import { POSTAL_CODE } from '../constants' +import type { PostalCodeRules } from '../types/rules' + +const rules: PostalCodeRules = { + country: null, + abbr: null, + postalCodeFrom: POSTAL_CODE, + fields: [ + { + hidden: true, + name: 'country', + maxLength: 100, + label: 'country', + size: 'medium', + }, + { + name: 'postalCode', + maxLength: 50, + label: 'postalCode', + size: 'small', + autoComplete: 'nope', + postalCodeAPI: false, + autoUpperCase: true, + }, + { + name: 'street', + label: 'addressLine1', + required: true, + size: 'xlarge', + }, + { + hidden: true, + name: 'number', + maxLength: 750, + label: 'number', + size: 'small', + autoComplete: 'nope', + }, + { + name: 'complement', + maxLength: 750, + label: 'addressLine2', + size: 'xlarge', + }, + { + hidden: true, + name: 'reference', + maxLength: 750, + label: 'reference', + size: 'xlarge', + }, + { + hidden: true, + name: 'neighborhood', + maxLength: 100, + label: 'neighborhood', + size: 'large', + }, + { + name: 'city', + maxLength: 100, + label: 'city', + required: true, + size: 'large', + }, + { + name: 'state', + maxLength: 100, + label: 'state', + required: true, + size: 'large', + }, + { + name: 'receiverName', + elementName: 'receiver', + maxLength: 750, + label: 'receiverName', + size: 'xlarge', + required: true, + }, + ], + geolocation: { + postalCode: { + valueIn: 'long_name', + types: ['postal_code'], + required: false, + }, + + number: { + valueIn: 'long_name', + types: ['street_number'], + required: false, + notApplicable: true, + }, + + street: { valueIn: 'long_name', types: ['route'] }, + + neighborhood: { + valueIn: 'long_name', + types: [ + 'neighborhood', + 'sublocality_level_1', + 'sublocality_level_2', + 'sublocality_level_3', + 'sublocality_level_4', + 'sublocality_level_5', + ], + }, + + state: { + valueIn: 'long_name', + types: ['administrative_area_level_1'], + }, + + city: { + valueIn: 'long_name', + types: ['administrative_area_level_2', 'locality'], + }, + + receiverName: { + required: true, + }, + }, + summary: [ + [ + { + name: 'street', + }, + { + delimiter: ' ', + name: 'number', + }, + { + delimiter: ', ', + name: 'complement', + }, + ], + [ + { + name: 'neighborhood', + delimiterAfter: ' - ', + }, + { + name: 'city', + }, + { + delimiter: ' - ', + name: 'state', + }, + ], + [ + { + name: 'postalCode', + }, + ], + ], +} + +export default rules diff --git a/react/country/IRL.ts b/react/country/IRL.ts index 61528128..f04e6e71 100644 --- a/react/country/IRL.ts +++ b/react/country/IRL.ts @@ -24,6 +24,7 @@ const rules: PostalCodeRules = { postalCodeAPI: true, size: 'small', autoComplete: 'nope', + autoUpperCase: true, }, { name: 'street', diff --git a/react/country/LTU.ts b/react/country/LTU.ts new file mode 100644 index 00000000..1946301a --- /dev/null +++ b/react/country/LTU.ts @@ -0,0 +1,159 @@ +import { POSTAL_CODE } from '../constants' +import type { PostalCodeRules } from '../types/rules' + +const rules: PostalCodeRules = { + country: null, + abbr: null, + postalCodeFrom: POSTAL_CODE, + fields: [ + { + hidden: true, + name: 'country', + maxLength: 100, + label: 'country', + size: 'medium', + }, + { + name: 'postalCode', + maxLength: 50, + label: 'postalCode', + size: 'small', + autoComplete: 'nope', + postalCodeAPI: false, + autoUpperCase: true, + }, + { + name: 'street', + label: 'addressLine1', + required: true, + size: 'xlarge', + }, + { + hidden: true, + name: 'number', + maxLength: 750, + label: 'number', + size: 'small', + autoComplete: 'nope', + }, + { + name: 'complement', + maxLength: 750, + label: 'addressLine2', + size: 'xlarge', + }, + { + hidden: true, + name: 'reference', + maxLength: 750, + label: 'reference', + size: 'xlarge', + }, + { + hidden: true, + name: 'neighborhood', + maxLength: 100, + label: 'neighborhood', + size: 'large', + }, + { + name: 'city', + maxLength: 100, + label: 'city', + required: true, + size: 'large', + }, + { + name: 'state', + maxLength: 100, + label: 'state', + required: true, + size: 'large', + }, + { + name: 'receiverName', + elementName: 'receiver', + maxLength: 750, + label: 'receiverName', + size: 'xlarge', + required: true, + }, + ], + geolocation: { + postalCode: { + valueIn: 'long_name', + types: ['postal_code'], + required: false, + }, + + number: { + valueIn: 'long_name', + types: ['street_number'], + required: false, + notApplicable: true, + }, + + street: { valueIn: 'long_name', types: ['route'] }, + + neighborhood: { + valueIn: 'long_name', + types: [ + 'neighborhood', + 'sublocality_level_1', + 'sublocality_level_2', + 'sublocality_level_3', + 'sublocality_level_4', + 'sublocality_level_5', + ], + }, + + state: { + valueIn: 'long_name', + types: ['administrative_area_level_1'], + }, + + city: { + valueIn: 'long_name', + types: ['administrative_area_level_2', 'locality'], + }, + + receiverName: { + required: true, + }, + }, + summary: [ + [ + { + name: 'street', + }, + { + delimiter: ' ', + name: 'number', + }, + { + delimiter: ', ', + name: 'complement', + }, + ], + [ + { + name: 'neighborhood', + delimiterAfter: ' - ', + }, + { + name: 'city', + }, + { + delimiter: ' - ', + name: 'state', + }, + ], + [ + { + name: 'postalCode', + }, + ], + ], +} + +export default rules diff --git a/react/country/MLT.ts b/react/country/MLT.ts index b2c46cfa..360d78b4 100644 --- a/react/country/MLT.ts +++ b/react/country/MLT.ts @@ -23,6 +23,7 @@ const rules: PostalCodeRules = { postalCodeAPI: false, size: 'small', autoComplete: 'nope', + autoUpperCase: true, }, { name: 'street', @@ -140,8 +141,8 @@ const rules: PostalCodeRules = { 'Żebbuġ (Zebbug)', 'Zebbug (Zebbug-Gozo)', 'Zejtun (Zejtun)', - 'Zurrieq (Zurrieq)' - ], + 'Zurrieq (Zurrieq)', + ], }, { name: 'receiverName', @@ -171,7 +172,8 @@ const rules: PostalCodeRules = { types: ['route'], handler: (address, googleAddress) => { address.street = { value: (googleAddress as { name: string }).name } - return address + + return address }, }, diff --git a/react/country/NLD.ts b/react/country/NLD.ts index b690d78a..352a791c 100644 --- a/react/country/NLD.ts +++ b/react/country/NLD.ts @@ -23,6 +23,7 @@ const rules: PostalCodeRules = { postalCodeAPI: false, size: 'small', autoComplete: 'nope', + autoUpperCase: true, }, { name: 'street', diff --git a/react/types/rules.ts b/react/types/rules.ts index 5404bfe1..f014f69d 100644 --- a/react/types/rules.ts +++ b/react/types/rules.ts @@ -43,6 +43,7 @@ export type PostalCodeFieldRule = RuleLabel & { maxLength?: number postalCodeAPI?: boolean autoComplete?: boolean | string + autoUpperCase?: boolean notApplicable?: boolean hidden?: boolean basedOn?: Fields diff --git a/react/validateAddress.ts b/react/validateAddress.ts index 7ebeaa24..2cdd3c21 100644 --- a/react/validateAddress.ts +++ b/react/validateAddress.ts @@ -95,6 +95,20 @@ export function validateChangedFields(changedFields, address, rules) { return reduce( changeFieldsNames, (resultAddress, fieldName) => { + const fieldRule = + rules.fields && rules.fields.find((field) => field.name === fieldName) + + // Convert value to uppercase if autoUpperCase is true + if ( + fieldRule && + fieldRule.autoUpperCase && + typeof resultAddress[fieldName].value === 'string' + ) { + resultAddress[fieldName].value = resultAddress[ + fieldName + ].value.toUpperCase() + } + const validationResult = validateField( resultAddress[fieldName].value, fieldName as Fields,