mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 14:42:05 +00:00
198 lines
5.9 KiB
TypeScript
198 lines
5.9 KiB
TypeScript
|
|
import { useMemo, useState } from "react";
|
||
|
|
import {
|
||
|
|
useApproveUplift,
|
||
|
|
useDenyUplift,
|
||
|
|
useUpliftsForDispatch,
|
||
|
|
} from "@/domain/uplifts/use-cases/use-uplift-actions";
|
||
|
|
import type { UpliftRequest } from "@/domain/uplifts/types/uplift";
|
||
|
|
import type { DispatchDetail } from "@/domain/work-orders/types/work-order";
|
||
|
|
import { useDispatchDetail } from "@/domain/work-orders/use-cases/use-work-order-detail";
|
||
|
|
import {
|
||
|
|
useAddChecklistItem,
|
||
|
|
useAddDispatchComment,
|
||
|
|
useAddDispatchSignoff,
|
||
|
|
useUpdateChecklistItem,
|
||
|
|
useUpdateDispatch,
|
||
|
|
useVerifyDispatch,
|
||
|
|
} from "@/domain/work-orders/use-cases/use-work-order-mutations";
|
||
|
|
import { isDispatchLocked } from "@/domain/work-orders/utils/is-dispatch-locked";
|
||
|
|
import { useAuthContext } from "@/providers/auth-context";
|
||
|
|
import { toDateInputValue } from "@/lib/time-utils";
|
||
|
|
import { buildDispatchEditForm } from "@/app/(protected)/workorders/_components/dispatch/dispatch-detail/build-dispatch-edit-form";
|
||
|
|
import type { DispatchEditFormState } from "@/app/(protected)/workorders/_components/dispatch/dispatch-detail/dispatch-edit-form";
|
||
|
|
|
||
|
|
export function useDispatchDetailController(
|
||
|
|
dispatchId: string | number,
|
||
|
|
workOrderId: string | number,
|
||
|
|
) {
|
||
|
|
const { user } = useAuthContext();
|
||
|
|
const { data: dispatch, isLoading } = useDispatchDetail(dispatchId);
|
||
|
|
const { data: uplifts = [] } = useUpliftsForDispatch(dispatchId);
|
||
|
|
|
||
|
|
const [editing, setEditing] = useState(false);
|
||
|
|
const [form, setForm] = useState<DispatchEditFormState>({
|
||
|
|
status: "",
|
||
|
|
nteAmount: "",
|
||
|
|
scheduledDate: "",
|
||
|
|
completedDate: "",
|
||
|
|
description: "",
|
||
|
|
});
|
||
|
|
const [newChecklistItem, setNewChecklistItem] = useState("");
|
||
|
|
const [commentText, setCommentText] = useState("");
|
||
|
|
const [sendEmail, setSendEmail] = useState(true);
|
||
|
|
const [sigCaptureType, setSigCaptureType] = useState<string | null>(null);
|
||
|
|
const [upliftAction, setUpliftAction] = useState<{
|
||
|
|
type: "approve" | "deny";
|
||
|
|
uplift: UpliftRequest;
|
||
|
|
} | null>(null);
|
||
|
|
|
||
|
|
const updateDispatchMutation = useUpdateDispatch(dispatchId, workOrderId);
|
||
|
|
const addCommentMutation = useAddDispatchComment(dispatchId);
|
||
|
|
const updateChecklistMutation = useUpdateChecklistItem(dispatchId);
|
||
|
|
const addChecklistMutation = useAddChecklistItem(dispatchId);
|
||
|
|
const addSignoffMutation = useAddDispatchSignoff(dispatchId);
|
||
|
|
const verifyMutation = useVerifyDispatch(dispatchId, workOrderId);
|
||
|
|
const approveUpliftMutation = useApproveUplift(dispatchId);
|
||
|
|
const denyUpliftMutation = useDenyUplift(dispatchId);
|
||
|
|
|
||
|
|
const userName =
|
||
|
|
(typeof user?.name === "string" ? user.name : undefined) ??
|
||
|
|
(typeof user?.fullname === "string" ? user.fullname : undefined) ??
|
||
|
|
"User";
|
||
|
|
|
||
|
|
const isLocked = dispatch ? isDispatchLocked(dispatch) : false;
|
||
|
|
|
||
|
|
const verifyState = useMemo(() => {
|
||
|
|
if (!dispatch) {
|
||
|
|
return { canVerify: false, missing: [] as string[] };
|
||
|
|
}
|
||
|
|
|
||
|
|
const checklistTotal = dispatch.checklistItems.length;
|
||
|
|
const checklistDone = dispatch.checklistItems.filter((item) => item.isCompleted).length;
|
||
|
|
const signoffCount = dispatch.signoffs.length;
|
||
|
|
const missing: string[] = [];
|
||
|
|
|
||
|
|
if (checklistTotal > 0 && checklistDone < checklistTotal) {
|
||
|
|
missing.push(`${checklistTotal - checklistDone} checklist item(s)`);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (signoffCount < 2) {
|
||
|
|
const types = dispatch.signoffs.map((signoff) => signoff.signoffType);
|
||
|
|
if (!types.includes("Customer")) {
|
||
|
|
missing.push("Customer sign-off");
|
||
|
|
}
|
||
|
|
if (!types.includes("Vendor")) {
|
||
|
|
missing.push("Vendor sign-off");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
missing,
|
||
|
|
canVerify: missing.length === 0 && (checklistTotal > 0 || signoffCount >= 2),
|
||
|
|
};
|
||
|
|
}, [dispatch]);
|
||
|
|
|
||
|
|
const beginEditing = () => {
|
||
|
|
if (dispatch) {
|
||
|
|
setForm(buildDispatchEditForm(dispatch));
|
||
|
|
}
|
||
|
|
setEditing(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleSave = () => {
|
||
|
|
updateDispatchMutation.mutate(
|
||
|
|
{
|
||
|
|
id: dispatchId,
|
||
|
|
status: form.status,
|
||
|
|
nteAmount: form.nteAmount ? parseFloat(form.nteAmount) : null,
|
||
|
|
scheduledDate: form.scheduledDate || null,
|
||
|
|
completedDate: form.completedDate || null,
|
||
|
|
description: form.description,
|
||
|
|
},
|
||
|
|
{ onSuccess: () => setEditing(false) },
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleCancelDispatch = (current: DispatchDetail) => {
|
||
|
|
if (!window.confirm("Are you sure you want to cancel this dispatch?")) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
updateDispatchMutation.mutate({
|
||
|
|
id: dispatchId,
|
||
|
|
status: "Cancelled",
|
||
|
|
nteAmount: current.nteAmount,
|
||
|
|
scheduledDate: toDateInputValue(current.scheduledDate) || null,
|
||
|
|
completedDate: toDateInputValue(current.completedDate) || null,
|
||
|
|
description: current.description,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleComment = (event: React.FormEvent) => {
|
||
|
|
event.preventDefault();
|
||
|
|
if (!commentText.trim()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
addCommentMutation.mutate(
|
||
|
|
{ text: commentText.trim(), sendEmail },
|
||
|
|
{ onSuccess: () => setCommentText("") },
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleUpliftConfirm = (note: string) => {
|
||
|
|
if (!upliftAction) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (upliftAction.type === "approve") {
|
||
|
|
approveUpliftMutation.mutate(
|
||
|
|
{ id: upliftAction.uplift.id, note },
|
||
|
|
{ onSuccess: () => setUpliftAction(null) },
|
||
|
|
);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
denyUpliftMutation.mutate(
|
||
|
|
{ id: upliftAction.uplift.id, note },
|
||
|
|
{ onSuccess: () => setUpliftAction(null) },
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
return {
|
||
|
|
dispatch,
|
||
|
|
isLoading,
|
||
|
|
uplifts,
|
||
|
|
editing,
|
||
|
|
form,
|
||
|
|
setForm,
|
||
|
|
newChecklistItem,
|
||
|
|
setNewChecklistItem,
|
||
|
|
commentText,
|
||
|
|
setCommentText,
|
||
|
|
sendEmail,
|
||
|
|
setSendEmail,
|
||
|
|
sigCaptureType,
|
||
|
|
setSigCaptureType,
|
||
|
|
upliftAction,
|
||
|
|
setUpliftAction,
|
||
|
|
isLocked,
|
||
|
|
userName,
|
||
|
|
verifyState,
|
||
|
|
beginEditing,
|
||
|
|
handleSave,
|
||
|
|
handleCancelDispatch,
|
||
|
|
handleComment,
|
||
|
|
handleUpliftConfirm,
|
||
|
|
setEditing,
|
||
|
|
updateDispatchMutation,
|
||
|
|
updateChecklistMutation,
|
||
|
|
addChecklistMutation,
|
||
|
|
addSignoffMutation,
|
||
|
|
verifyMutation,
|
||
|
|
approveUpliftMutation,
|
||
|
|
denyUpliftMutation,
|
||
|
|
addCommentMutation,
|
||
|
|
};
|
||
|
|
}
|