import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useMemo, useRef, useState } from "react"; import { useForm } from "react-hook-form"; import { z, ZodSchema } from "zod"; const useFormHandler = (formSchema:T,defaultValues:z.infer) => { type SchemaType = z.infer const [isInputChanged,setIsInputChanged]=useState(false) const [addValues,setAddValues]=useState>>({}) const form = useForm>({ resolver: zodResolver(formSchema), defaultValues }); const dirtyValues = form.formState.dirtyFields const isValuesSet=useRef(false) const getChangedFields=(values:Partial)=>{ const changedFields = Object.keys(dirtyValues).reduce>( (acc, key) => { const typedKey = key as keyof SchemaType; const selectedValue = values[typedKey]; if (selectedValue !== undefined) { acc[typedKey] = selectedValue as any; } return acc; }, {} ); return changedFields } useEffect(()=>{ if(isValuesSet.current)return const valuesToSet=Object.entries(addValues) if(!valuesToSet.length)return valuesToSet.map(([key,value])=>{ form.setValue(key as any,value ) }) isValuesSet.current=true },[addValues,form]) useEffect(() => { const subscription = form.watch((value, { name, type }) =>{ if(type === 'change' && !isInputChanged){ setIsInputChanged(true) } } ) return () => subscription.unsubscribe() }, [form.watch,form,isInputChanged]) const setFormValues = (values:Partial>)=>{ setAddValues(values) } const isChanged = useMemo(()=>{ return Object.values(getChangedFields(form.getValues()))?.length ? true : false },[form.getValues(),getChangedFields]) return { form, isInputChanged:isChanged, setIsInputChanged, getChangedFields, setFormValues } } export default useFormHandler