import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "react-router"; import { toast } from "react-toastify"; import { vendorOperationsApi } from "@/domain/vendor-operations/api/vendor-operations-api"; import type { VendorAssignmentPayload, VendorAssignmentResult, } from "@/domain/vendor-operations/types/vendor-operations"; import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api"; import type { WorkOrderFormSchemaValues } from "@/domain/work-orders/schemas/work-order-schema"; import { queryKeys } from "@/infra/query-key/query-key"; type SaveWorkOrderInput = { workOrderId?: string | number; values: WorkOrderFormSchemaValues; vendorAssignment?: VendorAssignmentPayload; }; type SaveWorkOrderResult = { workOrderId: string | number; assignment?: VendorAssignmentResult; }; class PartialWorkOrderSaveError extends Error { constructor(public readonly workOrderId: string | number) { super("Work order saved, but the vendor assignment could not be completed."); this.name = "PartialWorkOrderSaveError"; } } export function useSaveWorkOrder() { const navigate = useNavigate(); const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ workOrderId, values, vendorAssignment, }: SaveWorkOrderInput): Promise => { const savedWorkOrder = workOrderId ? await workOrdersApi.update(workOrderId, values) : await workOrdersApi.create(values); let assignment: VendorAssignmentResult | undefined; if (vendorAssignment) { try { assignment = await vendorOperationsApi.assignVendor(savedWorkOrder.id, vendorAssignment); } catch { throw new PartialWorkOrderSaveError(savedWorkOrder.id); } } return { workOrderId: savedWorkOrder.id, assignment }; }, onSuccess: ({ workOrderId, assignment }) => { void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.all }); void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.detail(workOrderId), }); toast.success("Work order saved successfully"); if (assignment?.conflicts.length) { const count = assignment.conflicts.length; toast.warning(`Vendor assigned with ${count} scheduling conflict${count > 1 ? "s" : ""}.`); } navigate(`/workorders/${workOrderId}`); }, onError: (error) => { if (error instanceof PartialWorkOrderSaveError) { void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.all }); void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.detail(error.workOrderId), }); toast.error(error.message); navigate(`/workorders/${error.workOrderId}`); return; } toast.error("Unable to save the work order. Please try again."); }, }); }