mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 10:28:59 +00:00
feat(work-orders): persist Schedule On clear from board and slide-over
Clearing a concrete date must go through the shared schedule patch so status can revert to Pending.
This commit is contained in:
parent
793230f0c2
commit
dee1578efe
9 changed files with 125 additions and 27 deletions
|
|
@ -18,6 +18,7 @@ import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-ta
|
||||||
import type { WizardWOStatus } from "@/domain/work-orders/types/work-order-wizard";
|
import type { WizardWOStatus } from "@/domain/work-orders/types/work-order-wizard";
|
||||||
import { deriveDayFields } from "@/domain/work-orders/utils/table-day-utils";
|
import { deriveDayFields } from "@/domain/work-orders/utils/table-day-utils";
|
||||||
import { toVendorTablePatch } from "@/domain/work-orders/utils/vendor-assignment-patch";
|
import { toVendorTablePatch } from "@/domain/work-orders/utils/vendor-assignment-patch";
|
||||||
|
import { withAutoScheduleStatus } from "@/domain/work-orders/utils/wo-lifecycle-transitions";
|
||||||
import { DocBadge } from "./slide-over-doc-badge";
|
import { DocBadge } from "./slide-over-doc-badge";
|
||||||
|
|
||||||
type SlideOverInfoTabEditViewProps = {
|
type SlideOverInfoTabEditViewProps = {
|
||||||
|
|
@ -39,6 +40,9 @@ function SlideOverScheduleOnField({
|
||||||
draft: WorkOrderTableRow;
|
draft: WorkOrderTableRow;
|
||||||
onDraftChange: (patch: Partial<WorkOrderTableRow>) => void;
|
onDraftChange: (patch: Partial<WorkOrderTableRow>) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const hasSchedule =
|
||||||
|
Boolean(draft.scheduledOn) || Boolean(draft.targetWeek) || Boolean(draft.scheduleEnd);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DateCell
|
<DateCell
|
||||||
value={draft.scheduledOn}
|
value={draft.scheduledOn}
|
||||||
|
|
@ -48,37 +52,59 @@ function SlideOverScheduleOnField({
|
||||||
scheduleEnd={draft.scheduleEnd}
|
scheduleEnd={draft.scheduleEnd}
|
||||||
schedMode={draft.schedMode}
|
schedMode={draft.schedMode}
|
||||||
onSave={(scheduledOn) =>
|
onSave={(scheduledOn) =>
|
||||||
onDraftChange({
|
onDraftChange(
|
||||||
scheduledOn,
|
withAutoScheduleStatus(draft, {
|
||||||
scheduleWeekOnly: false,
|
scheduledOn,
|
||||||
targetWeek: scheduledOn ? "" : draft.targetWeek,
|
scheduleWeekOnly: false,
|
||||||
scheduleEnd: "",
|
targetWeek: scheduledOn ? "" : draft.targetWeek,
|
||||||
schedMode: "date",
|
scheduleEnd: "",
|
||||||
isPastDue: false,
|
schedMode: "date",
|
||||||
...deriveDayFields(scheduledOn),
|
isPastDue: false,
|
||||||
})
|
...deriveDayFields(scheduledOn),
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
onSaveWeek={(weekStart) =>
|
onSaveWeek={(weekStart) =>
|
||||||
onDraftChange({
|
onDraftChange(
|
||||||
scheduledOn: "",
|
withAutoScheduleStatus(draft, {
|
||||||
targetWeek: weekStart,
|
scheduledOn: "",
|
||||||
scheduleWeekOnly: true,
|
targetWeek: weekStart,
|
||||||
scheduleEnd: "",
|
scheduleWeekOnly: true,
|
||||||
schedMode: "week",
|
scheduleEnd: "",
|
||||||
isPastDue: false,
|
schedMode: "week",
|
||||||
...deriveDayFields(""),
|
isPastDue: false,
|
||||||
})
|
...deriveDayFields(""),
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
onSaveRange={(start, end) =>
|
onSaveRange={(start, end) =>
|
||||||
onDraftChange({
|
onDraftChange(
|
||||||
scheduledOn: start,
|
withAutoScheduleStatus(draft, {
|
||||||
scheduleEnd: end,
|
scheduledOn: start,
|
||||||
schedMode: "range",
|
scheduleEnd: end,
|
||||||
scheduleWeekOnly: false,
|
schedMode: "range",
|
||||||
targetWeek: "",
|
scheduleWeekOnly: false,
|
||||||
isPastDue: false,
|
targetWeek: "",
|
||||||
...deriveDayFields(start),
|
isPastDue: false,
|
||||||
})
|
...deriveDayFields(start),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClear={
|
||||||
|
hasSchedule
|
||||||
|
? () =>
|
||||||
|
onDraftChange(
|
||||||
|
withAutoScheduleStatus(draft, {
|
||||||
|
scheduledOn: "",
|
||||||
|
targetWeek: "",
|
||||||
|
scheduleWeekOnly: false,
|
||||||
|
scheduleEnd: "",
|
||||||
|
schedMode: undefined,
|
||||||
|
isPastDue: false,
|
||||||
|
...deriveDayFields(""),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,15 @@ export function useWoTableRowHandlers({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
onScheduleClear: (id: string | number) => {
|
||||||
|
onPatch(id, applySchedulePatch("", false));
|
||||||
|
weekMoveNotify(weekMonday, {
|
||||||
|
onNavigate: () => {
|
||||||
|
onNavigateToDay(weekMonday);
|
||||||
|
onOpenAdvancedFilters?.();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
onDuplicateFound: (existing: WorkOrderTableRow) => {
|
onDuplicateFound: (existing: WorkOrderTableRow) => {
|
||||||
onDuplicateFound?.(existing);
|
onDuplicateFound?.(existing);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,11 @@ export function WoTableRowCells({
|
||||||
onSave={(date) => handlers.onScheduleDate(row.id, date)}
|
onSave={(date) => handlers.onScheduleDate(row.id, date)}
|
||||||
onSaveWeek={(week) => handlers.onScheduleWeek(row.id, week)}
|
onSaveWeek={(week) => handlers.onScheduleWeek(row.id, week)}
|
||||||
onSaveRange={(start, end) => handlers.onScheduleRange(row.id, start, end)}
|
onSaveRange={(start, end) => handlers.onScheduleRange(row.id, start, end)}
|
||||||
|
onClear={
|
||||||
|
Boolean(row.scheduledOn) || Boolean(row.targetWeek) || Boolean(row.scheduleEnd)
|
||||||
|
? () => handlers.onScheduleClear(row.id)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export type WoTableRowHandlers = {
|
||||||
onScheduleDate: (id: string | number, date: string) => void;
|
onScheduleDate: (id: string | number, date: string) => void;
|
||||||
onScheduleWeek: (id: string | number, week: string) => void;
|
onScheduleWeek: (id: string | number, week: string) => void;
|
||||||
onScheduleRange: (id: string | number, start: string, end: string) => void;
|
onScheduleRange: (id: string | number, start: string, end: string) => void;
|
||||||
|
onScheduleClear: (id: string | number) => void;
|
||||||
onDuplicateFound?: (existing: WorkOrderTableRow) => void;
|
onDuplicateFound?: (existing: WorkOrderTableRow) => void;
|
||||||
onOpenSlideOver: (row: WorkOrderTableRow) => void;
|
onOpenSlideOver: (row: WorkOrderTableRow) => void;
|
||||||
onRequestComplete?: (row: WorkOrderTableRow) => void;
|
onRequestComplete?: (row: WorkOrderTableRow) => void;
|
||||||
|
|
@ -89,6 +90,10 @@ function guardScheduleHandlers(
|
||||||
if (!canApplyWorkOrderTablePatch(row.status, { scheduledOn: start })) return;
|
if (!canApplyWorkOrderTablePatch(row.status, { scheduledOn: start })) return;
|
||||||
handlers.onScheduleRange(id, start, end);
|
handlers.onScheduleRange(id, start, end);
|
||||||
},
|
},
|
||||||
|
onScheduleClear: (id) => {
|
||||||
|
if (!canApplyWorkOrderTablePatch(row.status, { scheduledOn: "" })) return;
|
||||||
|
handlers.onScheduleClear(id);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,24 @@ describe("DateCell — Schedule On range", () => {
|
||||||
expect(onSave).not.toHaveBeenCalled();
|
expect(onSave).not.toHaveBeenCalled();
|
||||||
expect(onSaveRange).not.toHaveBeenCalled();
|
expect(onSaveRange).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
it("shows Clear when a concrete schedule exists", async () => {
|
||||||
|
const onClear = vi.fn();
|
||||||
|
renderWithProviders(
|
||||||
|
<DateCell
|
||||||
|
value="2026-06-01"
|
||||||
|
allowWeekMode
|
||||||
|
onSave={vi.fn()}
|
||||||
|
onSaveWeek={vi.fn()}
|
||||||
|
onSaveRange={vi.fn()}
|
||||||
|
onClear={onClear}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: /06-01/ }));
|
||||||
|
fireEvent.click(await screen.findByRole("button", { name: /clear/i }));
|
||||||
|
|
||||||
|
expect(onClear).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("DueDateCell — no Schedule On range tabs", () => {
|
describe("DueDateCell — no Schedule On range tabs", () => {
|
||||||
|
|
|
||||||
|
|
@ -151,4 +151,36 @@ describe("useWoTableRowHandlers schedule navigation (SH-240)", () => {
|
||||||
expect(onNavigateToDay).toHaveBeenCalledWith("2026-05-25");
|
expect(onNavigateToDay).toHaveBeenCalledWith("2026-05-25");
|
||||||
expect(onOpenAdvancedFilters).toHaveBeenCalled();
|
expect(onOpenAdvancedFilters).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("clears Schedule On and offers Advanced Filters navigation", () => {
|
||||||
|
const onNavigateToDay = vi.fn();
|
||||||
|
const onOpenAdvancedFilters = vi.fn();
|
||||||
|
const onPatch = vi.fn();
|
||||||
|
|
||||||
|
const { result } = renderHook(() =>
|
||||||
|
useWoTableRowHandlers({
|
||||||
|
tableData: buildTableData(),
|
||||||
|
weekMonday: "2026-05-18",
|
||||||
|
onNavigateToDay,
|
||||||
|
onOpenAdvancedFilters,
|
||||||
|
onOpenSlideOver: vi.fn(),
|
||||||
|
onOpenMedia: vi.fn(),
|
||||||
|
onPatch,
|
||||||
|
onScheduleHighlight: vi.fn(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
result.current.onScheduleClear("wo-1");
|
||||||
|
|
||||||
|
expect(onPatch).toHaveBeenCalledWith("wo-1", applySchedulePatch("", false));
|
||||||
|
expect(weekMoveNotify).toHaveBeenCalledWith(
|
||||||
|
"2026-05-18",
|
||||||
|
expect.objectContaining({ onNavigate: expect.any(Function) }),
|
||||||
|
);
|
||||||
|
|
||||||
|
const { onNavigate } = weekMoveNotify.mock.calls[0][1] as { onNavigate: () => void };
|
||||||
|
onNavigate();
|
||||||
|
expect(onNavigateToDay).toHaveBeenCalledWith("2026-05-18");
|
||||||
|
expect(onOpenAdvancedFilters).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ const handlers: WoTableRowHandlers = {
|
||||||
onScheduleDate: vi.fn(),
|
onScheduleDate: vi.fn(),
|
||||||
onScheduleWeek: vi.fn(),
|
onScheduleWeek: vi.fn(),
|
||||||
onScheduleRange: vi.fn(),
|
onScheduleRange: vi.fn(),
|
||||||
|
onScheduleClear: vi.fn(),
|
||||||
onOpenSlideOver: vi.fn(),
|
onOpenSlideOver: vi.fn(),
|
||||||
onOpenCompDoc: vi.fn(),
|
onOpenCompDoc: vi.fn(),
|
||||||
onOpenUplifts: vi.fn(),
|
onOpenUplifts: vi.fn(),
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ function handlers(overrides: Partial<WoTableRowHandlers> = {}): WoTableRowHandle
|
||||||
onScheduleDate: vi.fn(),
|
onScheduleDate: vi.fn(),
|
||||||
onScheduleWeek: vi.fn(),
|
onScheduleWeek: vi.fn(),
|
||||||
onScheduleRange: vi.fn(),
|
onScheduleRange: vi.fn(),
|
||||||
|
onScheduleClear: vi.fn(),
|
||||||
onOpenSlideOver: vi.fn(),
|
onOpenSlideOver: vi.fn(),
|
||||||
onReorder: vi.fn(),
|
onReorder: vi.fn(),
|
||||||
onDragStart: vi.fn(),
|
onDragStart: vi.fn(),
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ const handlers: WoTableRowHandlers = {
|
||||||
onScheduleDate: vi.fn(),
|
onScheduleDate: vi.fn(),
|
||||||
onScheduleWeek: vi.fn(),
|
onScheduleWeek: vi.fn(),
|
||||||
onScheduleRange: vi.fn(),
|
onScheduleRange: vi.fn(),
|
||||||
|
onScheduleClear: vi.fn(),
|
||||||
onOpenSlideOver: vi.fn(),
|
onOpenSlideOver: vi.fn(),
|
||||||
onOpenCompDoc: vi.fn(),
|
onOpenCompDoc: vi.fn(),
|
||||||
onOpenUplifts: vi.fn(),
|
onOpenUplifts: vi.fn(),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue