import { useCallback, useState } from 'react'; import * as yup from 'yup'; import { BooleanSchema, AnyObject, StringSchema } from 'yup'; const passwordErrorsInit: { translation: | 'register.validation.SHORT' | 'register.validation.NUMBER' | 'register.validation.CASE' | 'register.validation.SPECIAL'; isValid: boolean; }[] = [ { translation: 'register.validation.SHORT', isValid: false, }, { translation: 'register.validation.NUMBER', isValid: false, }, { translation: 'register.validation.CASE', isValid: false, }, { translation: 'register.validation.SPECIAL', isValid: false, }, ]; const numberRegexp = /\d+/; const caseRegexp = /(?=.*?[A-Z])(?=.*?[a-z])/; const specialRegexp = /[_+[!\]@#$;':,.?<>/"%^&*\\|()`~=-]+/; type PossibleFields = 'password' | 'confirmPassword' | 'email' | 'fullName' | 'terms'; export const useAuthValidation = (fields: Array) => { const [passwordErrors, setPasswordErrors] = useState(passwordErrorsInit); const changeHandler = useCallback((key: string, isValid: boolean) => { setPasswordErrors(prev => { const newErrors = [...prev]; const foundIdx = newErrors.findIndex(el => el.translation.includes(key)); newErrors[foundIdx].isValid = isValid; return newErrors; }); }, []); const schema = (() => { const yupShape: Record< string, StringSchema | BooleanSchema > = {}; if (fields?.includes('password')) { yupShape.password = yup .string() .required('register.validation.REQUIRED') .when('password', ([password]: (string | undefined)[], field) => { if (!password || password?.length <= 5) { changeHandler('SHORT', false); return field.min(6, 'register.validation.SHORT'); } else { changeHandler('SHORT', true); return field; } }) .when('password', ([password]: (string | undefined)[], field) => { if (!password || !numberRegexp.test(password)) { changeHandler('NUMBER', false); return field.matches(numberRegexp, { message: 'register.validation.NUMBER' }); } else { changeHandler('NUMBER', true); return field; } }) .when('password', ([password]: (string | undefined)[], field) => { if (!password || !caseRegexp.test(password)) { changeHandler('CASE', false); return field.matches(caseRegexp, { message: 'register.validation.CASE' }); } else { changeHandler('CASE', true); return field; } }) .when('password', ([password]: (string | undefined)[], field) => { if (!password || !specialRegexp.test(password)) { changeHandler('SPECIAL', false); return field.matches(specialRegexp, 'register.validation.SPECIAL'); } else { changeHandler('SPECIAL', true); return field; } }); } if (fields?.includes('confirmPassword')) { yupShape.confirmPassword = yup .string() .required('register.validation.REQUIRED') .oneOf([yup.ref('password')], 'register.validation.MATCH'); } if (fields?.includes('email')) { yupShape.email = yup.string().required('register.validation.REQUIRED').email('register.validation.EMAIL'); } if (fields?.includes('fullName')) { yupShape.fullName = yup .string() .required('register.validation.REQUIRED') .min(2, 'register.validation.SHORT') .max(20, 'register.validation.LONG'); } if (fields?.includes('terms')) { yupShape.terms = yup.bool().oneOf([true], 'register.validation.CHECKBOX'); } return yup.object().shape(yupShape, [['password', 'password']]); })(); return { schema, passwordErrors }; };