"use client" import { useEffect } from "react" import { useForm, type DefaultValues, type FieldValues, type UseFormReturn } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { useQuery, useQueryClient, type QueryKey } from "@tanstack/react-query" import type { ZodType } from "zod" type UseResourceFormOptions = { schema: ZodType defaultValues: DefaultValues resourceId?: string | null initialize?: (id: string) => Promise mapToFormValues: (data: TApiData) => TFormValues initialData?: TApiData | null queryKey?: QueryKey } type UseResourceFormReturn = { form: UseFormReturn isEditing: boolean isInitializing: boolean invalidate: () => void } export function useResourceForm({ schema, defaultValues, resourceId, initialize, mapToFormValues, initialData, queryKey, }: UseResourceFormOptions): UseResourceFormReturn { const isEditing = !!resourceId const queryClient = useQueryClient() const resolvedQueryKey = queryKey ?? ["resource", resourceId] const { data: queriedData, isLoading: isQueryLoading } = useQuery({ queryKey: resolvedQueryKey, queryFn: () => initialize!(resourceId!), enabled: isEditing && !!initialize, staleTime: 0, refetchOnMount: "always", }) const resolvedData = queriedData ?? (isEditing ? initialData : undefined) const form = useForm({ resolver: zodResolver(schema) as any, defaultValues, }) useEffect(() => { if (!isEditing) { if (initialData) { form.reset({ ...defaultValues, ...mapToFormValues(initialData) } as any) } else { form.reset(defaultValues) } return } if (resolvedData) { form.reset(mapToFormValues(resolvedData) as any) } }, [isEditing, resolvedData, initialData]) // eslint-disable-line react-hooks/exhaustive-deps const invalidate = () => { queryClient.invalidateQueries({ queryKey: resolvedQueryKey }) } return { form, isEditing, isInitializing: isEditing && !!initialize && isQueryLoading, invalidate } }