mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-05 16:32:06 +00:00
110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
|
|
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<typeof useForm<CompletionTemplateFormValues>>["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<CompletionTemplateDialogMode>(
|
||
|
|
template === null ? "create" : initialMode,
|
||
|
|
);
|
||
|
|
const form = useForm<CompletionTemplateFormValues>({
|
||
|
|
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,
|
||
|
|
};
|
||
|
|
}
|