diff --git a/src/app/(protected)/workorders/_components/list/table/to-inline-draft-row.ts b/src/app/(protected)/workorders/_components/list/table/to-inline-draft-row.ts index 1ec7ee46..1c4952ad 100644 --- a/src/app/(protected)/workorders/_components/list/table/to-inline-draft-row.ts +++ b/src/app/(protected)/workorders/_components/list/table/to-inline-draft-row.ts @@ -16,6 +16,7 @@ export function toInlineDraftRow(draft: WorkOrderTableDraft) { location: draft.location, dispatcherId: draft.dispatcherId, scheduledOn: draft.scheduledOn, + completedDate: "", dueDate: draft.dueDate, pm: draft.pm, serviceNotes: draft.serviceNotes, diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-cols.ts b/src/app/(protected)/workorders/_components/list/table/wo-table-cols.ts index 837c8622..e9c4f1ee 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-cols.ts +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-cols.ts @@ -12,8 +12,9 @@ export const WO_TABLE_COLS = [ { key: "appt", label: "APPT TIME", w: 128 }, { key: "status", label: "STATUS", w: 148 }, { key: "doc", label: "COMP DOC", w: 84 }, + { key: "completed", label: "COMPLETED DATE", w: 130 }, { key: "actions", label: "", w: 100 }, ] as const; -export const WO_TABLE_MIN_WIDTH = 1504; +export const WO_TABLE_MIN_WIDTH = 1634; export const WO_TABLE_ROW_HEIGHT = 52; diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx index 19c0ed93..0dfa7ba1 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx @@ -33,6 +33,14 @@ type WoTableInlineRowCellsProps = { onPatch: (patch: Partial) => void; }; +function InlineMutedDashCell() { + return ( + + — + + ); +} + export function WoTableInlineRowCells({ draft, weekDefault, @@ -164,9 +172,8 @@ export function WoTableInlineRowCells({ /> - - — - + + ); } diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx index 143cc46a..7974f536 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx @@ -3,6 +3,7 @@ import type { VendorDropdownItem } from "@/domain/work-orders/types/work-order"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; import { ApptTimeCell } from "./cells/appt-time-cell"; import { CompDocCell } from "./cells/comp-doc-cell"; +import { DateCell } from "./cells/date-cell"; import { PMTypeCell } from "./cells/pm-type-cell"; import { StatusCell } from "./cells/status-cell"; import { VendorCell } from "./cells/vendor-cell"; @@ -102,6 +103,17 @@ export function WoTableRowServiceCells({ onOpenMedia={() => handlers.onOpenMedia(row)} /> + e.stopPropagation()} + > + onPatchRow({ completedDate: date })} + /> + ); } diff --git a/src/domain/work-orders/types/work-order-board.ts b/src/domain/work-orders/types/work-order-board.ts index 22c9c043..64f5158e 100644 --- a/src/domain/work-orders/types/work-order-board.ts +++ b/src/domain/work-orders/types/work-order-board.ts @@ -147,6 +147,8 @@ export interface WorkOrderBoardRowApi { flagColor?: string | null; dueDate?: string | null; scheduledDate?: string | null; + /** ISO date when work was completed; optional on list rows until BE confirms. */ + completedDate?: string | null; targetWeek?: string | null; scheduleWeekOnly?: boolean | null; dayGroup?: string | null; diff --git a/src/domain/work-orders/utils/slide-over-draft.ts b/src/domain/work-orders/utils/slide-over-draft.ts index 4bc824e3..2b4a3226 100644 --- a/src/domain/work-orders/utils/slide-over-draft.ts +++ b/src/domain/work-orders/utils/slide-over-draft.ts @@ -18,6 +18,7 @@ export const SLIDE_OVER_EDIT_KEYS = [ "targetWeek", "scheduleWeekOnly", "dueDate", + "completedDate", "apptTime", "pm", "serviceNotes", diff --git a/src/test/domain/work-orders/mappers/completed-date-board-column.test.ts b/src/test/domain/work-orders/mappers/completed-date-board-column.test.ts new file mode 100644 index 00000000..9b74c71a --- /dev/null +++ b/src/test/domain/work-orders/mappers/completed-date-board-column.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from "vitest"; +import { WO_TABLE_COLS } from "@/app/(protected)/workorders/_components/list/table/wo-table-cols"; +import { expandScalarBoardOps } from "@/domain/work-orders/mappers/expand-scalar-board-ops"; +import { mapWorkOrderTableRow } from "@/domain/work-orders/mappers/work-order-table-row-mapper"; + +describe("COMPLETED DATE board column wiring", () => { + it("includes COMPLETED DATE column after COMP DOC", () => { + const keys = WO_TABLE_COLS.map((col) => col.key); + expect(keys).toContain("completed"); + expect(keys.indexOf("completed")).toBeGreaterThan(keys.indexOf("doc")); + }); + + it("expands completedDate patch to board field op", () => { + const ops = expandScalarBoardOps({ completedDate: "2026-07-30" }); + expect(ops).toEqual([{ field: "completedDate", value: "2026-07-30" }]); + }); + + it("maps completedDate returned by a board GET row", () => { + const row = mapWorkOrderTableRow({ + id: 42, + completedDate: "2026-07-30T00:00:00Z", + }); + + expect(row.completedDate).toBe("2026-07-30"); + }); +});