mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-05 00:12:09 +00:00
* fix(work-orders): address wizard create review findings
[recover] remove malicious eslint payload (was 166c63e4)
* fix(work-orders): remove legacy completedDate EditWorkorder path
[recover] remove malicious eslint payload (was f4e6132b)
* fix(work-orders): use local calendar day for completedDate
Restore todayIso() after parent merge reintroduced UTC slice, and keep the wizard-date-utils regression test.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(work-orders): send wizard status and clear POC notes on site change
Map draft.status to lifecycleStatus on board create, and reset pocNotes with POC fields when the wizard site changes.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(query): scope broadcast channel per account and clear on auth
Isolate TanStack Query broadcast by userId, dispose and clear on
logout/401, and extract vendor filter drawers for governance.
* feat(work-orders): board wizard create with service notes
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(work-orders): enforce single-service wizard create per SH-118
Use single service selection in the wizard and omit extraServices from board create.
* fix(vendors): restore filter drawer labels for e2e and visual CI
Use VendorFilterOptions again and keep the Apply filters footer label expected
by vendor Playwright specs and the committed visual baseline.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
101 lines
3.6 KiB
TypeScript
101 lines
3.6 KiB
TypeScript
import { useParams } from "react-router";
|
|
import { Box } from "@mui/material";
|
|
import { QueryErrorPanel } from "@/components/ui/query-error-panel";
|
|
import { DetailPageSkeleton } from "./_components/loading/detail-page-skeleton";
|
|
import { DispatchCreateModal } from "./_components/dispatch-create-modal";
|
|
import { DispatchDetailModal } from "./_components/dispatch-detail-modal";
|
|
import { WorkOrderActivityPanel } from "./_components/view/work-order-activity-panel";
|
|
import { WorkOrderDispatchesAccordion } from "./_components/view/work-order-dispatches-accordion";
|
|
import { WorkOrderVendorEditorDialog } from "./_components/view/work-order-vendor-editor-dialog";
|
|
import { WorkOrderViewAccordions } from "./_components/view/work-order-view-accordions";
|
|
import { WorkOrderViewDetails } from "./_components/view/work-order-view-details";
|
|
import { WorkOrderViewHeader } from "./_components/view/work-order-view-header";
|
|
import { useWorkOrderViewPage } from "./_hooks/use-work-order-view-page";
|
|
|
|
export default function WorkOrderViewPage() {
|
|
const { id } = useParams();
|
|
const workOrderId = id ?? "";
|
|
const view = useWorkOrderViewPage(workOrderId);
|
|
|
|
if (view.isLoading && !view.wo) {
|
|
return <DetailPageSkeleton variant="view" />;
|
|
}
|
|
|
|
if (!view.wo) {
|
|
return (
|
|
<Box className="p-4">
|
|
<QueryErrorPanel
|
|
message={view.error instanceof Error ? view.error.message : "Work order not found."}
|
|
onRetry={() => void view.refetch()}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Box className="flex flex-col gap-4 p-4">
|
|
<WorkOrderViewHeader
|
|
wo={view.wo}
|
|
workOrderId={workOrderId}
|
|
statusAnchor={view.statusAnchor}
|
|
onStatusAnchorChange={view.setStatusAnchor}
|
|
onStatusChange={(status) => view.statusMutation.mutate(status)}
|
|
onOpenDispatch={() => view.setDispatchOpen(true)}
|
|
/>
|
|
|
|
<WorkOrderViewDetails
|
|
wo={view.wo}
|
|
users={view.users}
|
|
assignAnchor={view.assignAnchor}
|
|
onAssignAnchorChange={view.setAssignAnchor}
|
|
onAssign={(userId, userName) => view.assignmentMutation.mutate({ userId, userName })}
|
|
onUnassign={() => view.assignmentMutation.mutate({ userId: "", userName: "" })}
|
|
/>
|
|
|
|
<WorkOrderViewAccordions wo={view.wo} />
|
|
|
|
<WorkOrderDispatchesAccordion
|
|
wo={view.wo}
|
|
onOpenDispatchDetail={view.setDispatchDetailId}
|
|
onOpenVendorEditor={view.openVendorEditor}
|
|
/>
|
|
|
|
<WorkOrderActivityPanel
|
|
customerComments={view.customerComments}
|
|
internalComments={view.internalComments}
|
|
auditLog={view.auditLog}
|
|
mentionUsers={view.mentionUsers}
|
|
isSubmitting={view.commentMutation.isPending}
|
|
onSubmitComment={view.submitComment}
|
|
/>
|
|
|
|
{view.dispatchOpen && (
|
|
<DispatchCreateModal
|
|
workOrder={view.wo}
|
|
onClose={() => view.setDispatchOpen(false)}
|
|
onDispatched={() => void view.refetch()}
|
|
/>
|
|
)}
|
|
{view.dispatchDetailId != null && (
|
|
<DispatchDetailModal
|
|
dispatchId={view.dispatchDetailId}
|
|
workOrderId={workOrderId}
|
|
onClose={() => view.setDispatchDetailId(null)}
|
|
onUpdated={() => void view.refetch()}
|
|
/>
|
|
)}
|
|
|
|
<WorkOrderVendorEditorDialog
|
|
editor={view.vendorEditor}
|
|
loading={view.vendorEditorLoading}
|
|
error={view.vendorEditorError}
|
|
isSaving={view.vendorMutation.isPending}
|
|
onClose={() => {
|
|
if (!view.vendorMutation.isPending) view.setVendorEditor(null);
|
|
}}
|
|
onSave={view.saveVendorEditor}
|
|
onEditorChange={view.setVendorEditor}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|