import { castArray } from 'lodash';
import type { ValidateFieldsError } from 'async-validator';
import { UseFormValidation } from '../form-types';
import { FormItemContext, FormValidateCallback, FormValidateResult } from '../components/form-item/form-item-types';
export default function useFormValidation(itemContexts: FormItemContext[]): UseFormValidation {
const getValidateFields = (fields: string[]) => {
if (!itemContexts.length) {
return [];
}
const normalizedFields = castArray(fields);
const filteredFields = normalizedFields.length
? itemContexts.filter((context) => context.field && normalizedFields.includes(context.field))
: itemContexts;
if (!filteredFields.length) {
return [];
}
return filteredFields;
};
const execValidateFields = async (fields: string[] = []): FormValidateResult => {
const validateFields = getValidateFields(fields);
if (!validateFields.length) {
return true;
}
let errors: ValidateFieldsError = {};
for (const field of validateFields) {
try {
await field.validate('');
} catch (err) {
errors = {
...errors,
...(err as ValidateFieldsError),
};
}
}
if (!Object.keys(errors).length) {
return true;
}
return Promise.reject(errors);
};
const validateFields = async (fields: string[] = [], callback?: FormValidateCallback) => {
try {
const result = await execValidateFields(fields);
if (result) {
callback?.(result);
}
return result;
} catch (err) {
const invalidFields = err as ValidateFieldsError;
callback?.(false, invalidFields);
return !callback && Promise.reject(invalidFields);
}
};
const validate = async (callback?: FormValidateCallback): FormValidateResult => validateFields(undefined, callback);
const clearValidate = (fields: string[] = []) => {
getValidateFields(fields).forEach((field) => field.clearValidate());
};
const resetFields = (fields: string[] = []) => {
getValidateFields(fields).forEach((field) => field.resetField());
};
return { validate, validateFields, resetFields, clearValidate };
}