diff --git a/packages/account/src/Configs/personal-details-config.js b/packages/account/src/Configs/personal-details-config.js index 0e47264846bf..a994b15edf82 100644 --- a/packages/account/src/Configs/personal-details-config.js +++ b/packages/account/src/Configs/personal-details-config.js @@ -29,7 +29,7 @@ const personal_details_config = ({ residence_list, account_settings, is_appstore rules: [ ['req', localize('First name is required.')], ['length', localize('First name should be between 2 and 50 characters.'), { min: 2, max: 50 }], - ['letter_symbol', getErrorMessages().letter_symbol()], + ['name', getErrorMessages().name()], ], }, last_name: { @@ -38,7 +38,7 @@ const personal_details_config = ({ residence_list, account_settings, is_appstore rules: [ ['req', localize('Last name is required.')], ['length', localize('Last name should be between 2 and 50 characters.'), { min: 2, max: 50 }], - ['letter_symbol', getErrorMessages().letter_symbol()], + ['name', getErrorMessages().name()], ], }, date_of_birth: { diff --git a/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx b/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx index 41fcbcae844a..b4da912be5b0 100644 --- a/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx +++ b/packages/account/src/Sections/Profile/PersonalDetails/personal-details.jsx @@ -35,6 +35,7 @@ import { routes, WS, useIsMounted, + validName, } from '@deriv/shared'; import { Localize, localize } from '@deriv/translations'; import { withRouter } from 'react-router'; @@ -314,8 +315,6 @@ export const PersonalDetailsForm = ({ } validateValues(val => val, required_fields, localize('This field is required')); - const only_alphabet_fields = ['first_name', 'last_name']; - validateValues(validLetterSymbol, only_alphabet_fields, localize('Only alphabet is allowed')); const residence_fields = ['citizen']; const validateResidence = val => getLocation(residence_list, val, 'value'); @@ -351,12 +350,19 @@ export const PersonalDetailsForm = ({ const min_name = 2; const max_name = 50; - if (values.first_name && !validLength(values.first_name.trim(), { min: min_name, max: max_name })) { - errors.first_name = localize('You should enter 2-50 characters.'); - } - if (values.last_name && !validLength(values.last_name.trim(), { min: min_name, max: max_name })) { - errors.last_name = localize('You should enter 2-50 characters.'); - } + const validateName = (name, field) => { + if (name) { + if (!validLength(name.trim(), { min: min_name, max: max_name })) { + errors[field] = localize('You should enter 2-50 characters.'); + } else if (!validName(name)) { + // validName() has the exact regex used at the backend for allowing non digit characters including accented unicode characters. + // two or more space between name not allowed. + errors[field] = localize('Letters, spaces, periods, hyphens, apostrophes only.'); + } + } + }; + validateName(values.first_name, 'first_name'); + validateName(values.last_name, 'last_name'); if (values.phone) { // minimum characters required is 9 numbers (excluding +- signs or space) diff --git a/packages/core/src/Constants/form-error-messages.js b/packages/core/src/Constants/form-error-messages.js index a0ca7bbbf6da..b69d902b55ad 100644 --- a/packages/core/src/Constants/form-error-messages.js +++ b/packages/core/src/Constants/form-error-messages.js @@ -11,7 +11,7 @@ export const FORM_ERROR_MESSAGES = { }), email: () => localize('Invalid email address.'), general: () => localize('Only letters, numbers, space, hyphen, period, and apostrophe are allowed.'), - letter_symbol: () => localize('Letters, spaces, periods, hyphens, apostrophes only'), + name: () => localize('Letters, spaces, periods, hyphens, apostrophes only.'), password: () => localize('Password should have lower and uppercase English letters with numbers.'), po_box: () => localize('P.O. Box is not accepted in address'), phone: () => localize('Please enter a valid phone number (e.g. +15417541234).'), diff --git a/packages/shared/src/utils/validation/declarative-validation-rules.ts b/packages/shared/src/utils/validation/declarative-validation-rules.ts index d4ef06025b63..313d72c320fa 100644 --- a/packages/shared/src/utils/validation/declarative-validation-rules.ts +++ b/packages/shared/src/utils/validation/declarative-validation-rules.ts @@ -24,6 +24,7 @@ export const validPostCode = (value: string) => value === '' || /^[A-Za-z0-9][A- export const validTaxID = (value: string) => /(?!^$|\s+)[A-Za-z0-9./\s-]$/.test(value); export const validPhone = (value: string) => /^\+?([0-9-]+\s)*[0-9-]+$/.test(value); export const validLetterSymbol = (value: string) => /^[A-Za-z]+([a-zA-Z.' -])*[a-zA-Z.' -]+$/.test(value); +export const validName = (value: string) => /^(?!.*\s{2,})[\p{L}\s'.-]{2,50}$/u.test(value); export const validLength = (value = '', options: TOptions) => (options.min ? value.length >= options.min : true) && (options.max ? value.length <= options.max : true); export const validPassword = (value: string) => /(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]+/.test(value); @@ -108,9 +109,9 @@ const initPreBuildDVRs = () => ({ message: form_error_messages.general, }, length: { func: validLength, message: '' }, // Message will be set in validLength function on initiation - letter_symbol: { - func: validLetterSymbol, - message: form_error_messages.letter_symbol, + name: { + func: validName, + message: form_error_messages.name, }, number: { func: (...args: [string, TOptions, Record]) => { diff --git a/packages/shared/src/utils/validation/form-error-messages-types.ts b/packages/shared/src/utils/validation/form-error-messages-types.ts index bc2099a1738a..4496c0ae7225 100644 --- a/packages/shared/src/utils/validation/form-error-messages-types.ts +++ b/packages/shared/src/utils/validation/form-error-messages-types.ts @@ -6,7 +6,7 @@ export type TFormErrorMessagesTypes = Record< | 'barrier' | 'email' | 'general' - | 'letter_symbol' + | 'name' | 'password' | 'po_box' | 'phone'