import { zodResolver } from "@hookform/resolvers/zod"; import { useState } from "react"; import { useForm, useWatch } from "react-hook-form"; import { COMPLETION_TEMPLATE_COPY } from "@/domain/completion-templates/constants/completion-template-constants"; import { toCompletionTemplateFormValues, toCompletionTemplateInput, } from "@/domain/completion-templates/mappers/completion-template-mapper"; import { completionTemplateFormSchema, type CompletionTemplateFormValues, } from "@/domain/completion-templates/schemas/completion-template-schema"; import type { CompletionTemplate } from "@/domain/completion-templates/types/completion-template"; import { isTitleRequiredError, useCreateCompletionTemplate, useUpdateCompletionTemplate, } from "@/domain/completion-templates/use-cases/use-completion-template-mutations"; import type { CompletionTemplatePreviewValues } from "./completion-template-preview"; export type CompletionTemplateDialogMode = "create" | "view" | "edit"; type UseCompletionTemplateDialogOptions = { template: CompletionTemplate | null; initialMode: CompletionTemplateDialogMode; onClose: () => void; onSaved: (template: CompletionTemplate) => void; }; function usePreviewValues( control: ReturnType>["control"], ): CompletionTemplatePreviewValues { const watched = useWatch({ control }); return { name: watched.name ?? "", extraSafetyNote: watched.extraSafetyNote ?? null, procedures: (watched.procedures ?? []).map((procedure) => ({ name: procedure?.name ?? "", description: procedure?.description ?? "", })), }; } export function useCompletionTemplateDialog({ template, initialMode, onClose, onSaved, }: UseCompletionTemplateDialogOptions) { const [mode, setMode] = useState( template === null ? "create" : initialMode, ); const form = useForm({ resolver: zodResolver(completionTemplateFormSchema), defaultValues: toCompletionTemplateFormValues(template), }); const previewValues = usePreviewValues(form.control); const create = useCreateCompletionTemplate(); const update = useUpdateCompletionTemplate(); function showServerTitleError(error: Error) { if (!isTitleRequiredError(error)) return; form.setError( "name", { message: COMPLETION_TEMPLATE_COPY.titleRequired }, { shouldFocus: true }, ); } const submit = form.handleSubmit((values) => { const input = toCompletionTemplateInput(values); if (template === null) { create.mutate(input, { onSuccess: onClose, onError: showServerTitleError }); return; } update.mutate( { template, input }, { onSuccess: (saved) => { form.reset(toCompletionTemplateFormValues(saved)); setMode("view"); onSaved(saved); }, onError: showServerTitleError, }, ); }); /** Discards unsaved edits: back to the template as it was, or closed when creating. */ function cancel() { if (template === null) { onClose(); return; } form.reset(toCompletionTemplateFormValues(template)); setMode("view"); } return { mode, isEditing: mode !== "view", form, previewValues, submit, cancel, startEditing: () => setMode("edit"), isSaving: create.isPending || update.isPending, }; }