diff --git a/src/shared/config/errors/types.ts b/src/shared/config/errors/types.ts index 5cdc46ce..fa83e0a7 100644 --- a/src/shared/config/errors/types.ts +++ b/src/shared/config/errors/types.ts @@ -5,7 +5,7 @@ interface DefaultError { type LocationTypeError = 'body' | 'query'; -interface FormFieldError extends DefaultError { +export interface FormFieldError extends DefaultError { location: [Extract, string]; } diff --git a/src/shared/ui/ManagedForm/index.tsx b/src/shared/ui/ManagedForm/index.tsx index 5e403782..22c97e6b 100644 --- a/src/shared/ui/ManagedForm/index.tsx +++ b/src/shared/ui/ManagedForm/index.tsx @@ -7,6 +7,7 @@ import { checkIsFormFieldsError, getErrorMessage } from '@shared/config'; import classes from './styles.module.less'; import { ManagedFormProps } from './types'; +import { cleanErrors, showErrorsInFields } from './utils'; /** Form component to manage the request and results of a form request */ export const ManagedForm = ({ @@ -49,11 +50,7 @@ export const ManagedForm = ({ if (checkIsFormFieldsError(error) && error.response) { message = 'Form error has occurred'; - const fieldErrors = error.response.data.error.details.map((field) => ({ - name: field.location[1], - errors: [field.message], - })); - form.setFields(fieldErrors); + showErrorsInFields(form, error.response.data.error.details); } notification.error({ @@ -63,20 +60,8 @@ export const ManagedForm = ({ }); }; - // Clean error from backend after field change value const onValuesChange = (values: T) => { - Object.keys(values).forEach((field) => { - const error = form.getFieldError(field); - if (!error.length) { - return; - } - form.setFields([ - { - name: field, - errors: [], - }, - ]); - }); + cleanErrors(form, values); }; return ( diff --git a/src/shared/ui/ManagedForm/utils/cleanErrors/index.ts b/src/shared/ui/ManagedForm/utils/cleanErrors/index.ts new file mode 100644 index 00000000..edef1686 --- /dev/null +++ b/src/shared/ui/ManagedForm/utils/cleanErrors/index.ts @@ -0,0 +1,28 @@ +import { FormInstance } from 'antd'; + +/** + * Util for cleaning field error text from backend while change its value + * + * @param form - Form instance. + * @param values - Form values that have changed. + * + */ +export const cleanErrors = (form: FormInstance, values: object, parentPath: string[] = []): void => { + Object.entries(values).forEach(([key, value]) => { + const currentPath = [...parentPath, key]; + + if (typeof value === 'object' && value !== null && !Array.isArray(value)) { + cleanErrors(form, value, currentPath); + return; + } + const error = form.getFieldError(currentPath); + if (error.length) { + form.setFields([ + { + name: currentPath, + errors: [], + }, + ]); + } + }); +}; diff --git a/src/shared/ui/ManagedForm/utils/index.ts b/src/shared/ui/ManagedForm/utils/index.ts new file mode 100644 index 00000000..5b9ea7e9 --- /dev/null +++ b/src/shared/ui/ManagedForm/utils/index.ts @@ -0,0 +1,2 @@ +export * from './cleanErrors'; +export * from './showErrorsInFields'; diff --git a/src/shared/ui/ManagedForm/utils/showErrorsInFields/index.ts b/src/shared/ui/ManagedForm/utils/showErrorsInFields/index.ts new file mode 100644 index 00000000..159b38a5 --- /dev/null +++ b/src/shared/ui/ManagedForm/utils/showErrorsInFields/index.ts @@ -0,0 +1,33 @@ +import { FormFieldError } from '@shared/config'; +import { FormInstance } from 'antd'; + +/** + * Util for processing and displaying form field errors from backend + * + * @param form - Form instance + * @param errors - Array of objects with paths to fields contains an error from backend + * + */ +export const showErrorsInFields = (form: FormInstance, errors: FormFieldError[]): void => { + const fieldErrors = errors + .map((field) => { + // Keep only valid parts of the path + const validPath = field.location.reduce((acc, key) => { + const currentPath = [...acc, key]; + // Check if the path to the current key exists + if (typeof form.getFieldValue(currentPath) === 'object' || form.getFieldInstance(currentPath)) { + acc.push(key); + } + return acc; + }, []); + + return { + name: validPath, + errors: [field.message], + }; + }) + // Remove errors without a valid path + .filter(({ name }) => name.length > 0); + + form.setFields(fieldErrors); +};