import React, { useEffect } from "react"; import { useForm as useHookForm, UseFormProps as UseHookFormProps, UseFormReturn, FieldValues, UseFormHandleSubmit, SubmitHandler, SubmitErrorHandler, } from "react-hook-form"; import { BaseRecord, HttpError, useForm as useFormCore, useWarnAboutChange, UseFormProps as UseFormCoreProps, UseFormReturnType as UseFormReturnTypeCore, } from "@pankod/refine-core"; export type UseFormReturnType< TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}, > = UseFormReturn & { refineCore: UseFormReturnTypeCore; saveButtonProps: { disabled: boolean; onClick: (e: React.BaseSyntheticEvent) => void; }; }; export type UseFormProps< TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}, > = { /** * Configuration object for the core of the [useForm](/docs/api-reference/core/hooks/useForm/) * @type [`UseFormCoreProps`](/docs/api-reference/core/hooks/useForm/#properties) */ refineCoreProps?: UseFormCoreProps; /** * When you have unsaved changes and try to leave the current page, **refine** shows a confirmation modal box. * @default `false*` */ warnWhenUnsavedChanges?: boolean; } & UseHookFormProps; export const useForm = < TData extends BaseRecord = BaseRecord, TError extends HttpError = HttpError, TVariables extends FieldValues = FieldValues, TContext extends object = {}, >({ refineCoreProps, warnWhenUnsavedChanges: warnWhenUnsavedChangesProp, ...rest }: UseFormProps = {}): UseFormReturnType< TData, TError, TVariables, TContext > => { const { warnWhenUnsavedChanges: warnWhenUnsavedChangesRefine, setWarnWhen, } = useWarnAboutChange(); const warnWhenUnsavedChanges = warnWhenUnsavedChangesProp ?? warnWhenUnsavedChangesRefine; const useFormCoreResult = useFormCore({ ...refineCoreProps, }); const { queryResult, onFinish, formLoading } = useFormCoreResult; const useHookFormResult = useHookForm({ ...rest, }); const { watch, reset, getValues, handleSubmit: handleSubmitReactHookForm, } = useHookFormResult; useEffect(() => { if (typeof queryResult?.data !== "undefined") { const fields: any = {}; const registeredFields = Object.keys(getValues()); Object.entries(queryResult?.data?.data || {}).forEach( ([key, value]) => { if (registeredFields.includes(key)) { fields[key] = value; } }, ); reset(fields as any); } }, [queryResult?.data]); useEffect(() => { const subscription = watch((values: any, { type }: { type?: any }) => { if (type === "change") { onValuesChange(values); } }); return () => subscription.unsubscribe(); }, [watch]); const onValuesChange = (changeValues: Record) => { if (warnWhenUnsavedChanges) { setWarnWhen(true); } return changeValues; }; const handleSubmit: UseFormHandleSubmit = (onValid, onInvalid) => async (e) => { setWarnWhen(false); return await handleSubmitReactHookForm(onValid, onInvalid)(e); }; const saveButtonProps = { disabled: formLoading, onClick: (e: React.BaseSyntheticEvent) => { handleSubmit(onFinish, () => false)(e); }, }; return { ...useHookFormResult, handleSubmit, refineCore: useFormCoreResult, saveButtonProps, }; };