mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-04 18:22:05 +00:00
* feat(vendors): complete operations roadmap frontend * test(vendors): cover work order assignment flow * fix(vendors): address review feedback * fix(vendors): prevent stale preference saves * fix(vendors): require truthful appointment bounds
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
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<SaveWorkOrderResult> => {
|
|
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.");
|
|
},
|
|
});
|
|
}
|