import { useMutation, useQueryClient, type QueryClient, type UseMutationResult, } from "@tanstack/react-query"; import { isHTTPError } from "ky"; import { toast } from "react-toastify"; import { completionTemplatesApi } from "@/domain/completion-templates/api/completion-templates-api"; import { COMPLETION_TEMPLATE_COPY } from "@/domain/completion-templates/constants/completion-template-constants"; import type { CompletionTemplate, CompletionTemplateInput, } from "@/domain/completion-templates/types/completion-template"; import { queryKeys } from "@/infra/query-key/query-key"; interface UpdateCompletionTemplateVariables { template: CompletionTemplate; input: CompletionTemplateInput; } /** The server's blank-title rejection, which the form shows on the title field instead. */ export function isTitleRequiredError(error: Error): boolean { if (!isHTTPError(error) || error.response.status !== 422) return false; const body: unknown = error.data; return ( typeof body === "object" && body !== null && "code" in body && body.code === "TitleRequired" ); } function invalidateTemplates(queryClient: QueryClient) { void queryClient.invalidateQueries({ queryKey: queryKeys.completionTemplates.all }); // The Services registry lists template names and clears links to a deleted template. void queryClient.invalidateQueries({ queryKey: queryKeys.services.all }); } function toastFailure(error: Error, fallback: string) { if (isTitleRequiredError(error)) return; toast.error(error.message || fallback); } export function useCreateCompletionTemplate(): UseMutationResult< CompletionTemplate, Error, CompletionTemplateInput > { const queryClient = useQueryClient(); return useMutation({ mutationFn: (input: CompletionTemplateInput) => completionTemplatesApi.create(input), onSuccess: () => { invalidateTemplates(queryClient); toast.success(COMPLETION_TEMPLATE_COPY.added); }, onError: (error: Error) => toastFailure(error, "Failed to add template"), }); } export function useUpdateCompletionTemplate(): UseMutationResult< CompletionTemplate, Error, UpdateCompletionTemplateVariables > { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ template, input }: UpdateCompletionTemplateVariables) => completionTemplatesApi.update(template, input), onSuccess: () => { invalidateTemplates(queryClient); toast.success(COMPLETION_TEMPLATE_COPY.updated); }, onError: (error: Error) => toastFailure(error, "Failed to update template"), }); } export function useDeleteCompletionTemplate(): UseMutationResult { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: number) => completionTemplatesApi.delete(id), onSuccess: () => { invalidateTemplates(queryClient); toast.success(COMPLETION_TEMPLATE_COPY.deleted); }, onError: (error: Error) => toastFailure(error, "Failed to delete template"), }); }