import { useState, ChangeEvent, FormEvent } from 'react'; interface UseFormOptions { initialValues: T; onSubmit: (values: T) => void | Promise; validate?: (values: T) => Partial>; } /** * Hook personnalisé pour gérer les formulaires * @param options Configuration du formulaire (initialValues, onSubmit, validate) * @returns Méthodes et états pour gérer le formulaire */ export function useForm>({ initialValues, onSubmit, validate, }: UseFormOptions) { const [values, setValues] = useState(initialValues); const [errors, setErrors] = useState>>({}); const [touched, setTouched] = useState>>({}); const [isSubmitting, setIsSubmitting] = useState(false); /** * Gère le changement de valeur d'un champ */ const handleChange = ( e: ChangeEvent ) => { const { name, value, type } = e.target; const fieldValue = type === 'checkbox' ? (e.target as HTMLInputElement).checked : value; setValues((prev) => ({ ...prev, [name]: fieldValue, })); // Valider le champ si une fonction de validation est fournie if (validate && touched[name as keyof T]) { const validationErrors = validate({ ...values, [name]: fieldValue, }); setErrors((prev) => ({ ...prev, [name]: validationErrors[name as keyof T], })); } }; /** * Marque un champ comme touché (pour afficher les erreurs) */ const handleBlur = ( e: ChangeEvent ) => { const { name } = e.target; setTouched((prev) => ({ ...prev, [name]: true, })); // Valider le champ au blur if (validate) { const validationErrors = validate(values); setErrors((prev) => ({ ...prev, [name]: validationErrors[name as keyof T], })); } }; /** * Gère la soumission du formulaire */ const handleSubmit = async (e: FormEvent) => { e.preventDefault(); // Marquer tous les champs comme touchés const allTouched = Object.keys(values).reduce( (acc, key) => ({ ...acc, [key]: true }), {} ); setTouched(allTouched); // Valider tous les champs if (validate) { const validationErrors = validate(values); setErrors(validationErrors); // Ne pas soumettre si des erreurs existent if (Object.keys(validationErrors).length > 0) { return; } } // Soumettre le formulaire setIsSubmitting(true); try { await onSubmit(values); } finally { setIsSubmitting(false); } }; /** * Réinitialise le formulaire */ const reset = () => { setValues(initialValues); setErrors({}); setTouched({}); setIsSubmitting(false); }; /** * Définit manuellement une valeur */ const setValue = (name: keyof T, value: any) => { setValues((prev) => ({ ...prev, [name]: value, })); }; /** * Définit manuellement une erreur */ const setError = (name: keyof T, error: string) => { setErrors((prev) => ({ ...prev, [name]: error, })); }; return { values, errors, touched, isSubmitting, handleChange, handleBlur, handleSubmit, reset, setValue, setError, }; }