diff --git a/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts b/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts index bebd1255..1724dc1e 100644 --- a/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts +++ b/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts @@ -19,7 +19,7 @@ function resolveInlineDraftSchedule(draft: WorkOrderTableDraft) { return { scheduleWeekOnly, status: resolveCreationStatus({ - status: draft.status || "Incomplete", + status: draft.status || "Pending", scheduledOn: draft.scheduledOn, scheduleWeekOnly, }), 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 319333ac..a5a89611 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 @@ -230,7 +230,7 @@ export function WoTableInlineRowCells({ dispatcherId={draft.dispatcherId} users={users} onSave={(id) => { - onPatch({ dispatcherId: id, status: draft.status || "Incomplete" }); + onPatch({ dispatcherId: id, status: draft.status || "Pending" }); }} /> diff --git a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-draft.ts b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-draft.ts index c0d45525..add130ff 100644 --- a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-draft.ts +++ b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-draft.ts @@ -9,7 +9,6 @@ export function useNewWoWizardDraft(open: boolean) { const [step, setStep] = useState(1); const [draft, setDraft] = useState({ ...EMPTY_WIZARD_DRAFT, - status: "Incomplete", }); const [svcOpen, setSvcOpen] = useState(false); const [svcSearch, setSvcSearch] = useState(""); @@ -18,7 +17,7 @@ export function useNewWoWizardDraft(open: boolean) { useEffect(() => { if (open) { setStep(1); - setDraft({ ...EMPTY_WIZARD_DRAFT, status: "Incomplete" }); + setDraft({ ...EMPTY_WIZARD_DRAFT }); setSvcOpen(false); setSvcSearch(""); setShowErrors(false); diff --git a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-state.ts b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-state.ts index 8f6b1e66..79c81e59 100644 --- a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-state.ts +++ b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-state.ts @@ -40,7 +40,6 @@ export function useNewWoWizardState({ const [showErrors, setShowErrors] = useState(false); const [draft, setDraft] = useState({ ...EMPTY_WIZARD_DRAFT, - status: "Incomplete", }); const [pocAutoFilledFor, setPocAutoFilledFor] = useState(""); @@ -83,7 +82,7 @@ export function useNewWoWizardState({ if (open) { setStep(1); setShowErrors(false); - setDraft({ ...EMPTY_WIZARD_DRAFT, status: "Incomplete" }); + setDraft({ ...EMPTY_WIZARD_DRAFT }); setPocAutoFilledFor(""); setDuplicateRow(null); } diff --git a/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary-rows.ts b/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary-rows.ts index e49e267a..4db322aa 100644 --- a/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary-rows.ts +++ b/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary-rows.ts @@ -53,6 +53,6 @@ export function buildWizardSidebarSummaryRows(draft: WorkOrderWizardDraft): [str ["Technician", draft.vendorName || "—"], ["Company", draft.vendorName || "—"], ["Appt time", draft.apptStart ? formatApptRange(draft.apptStart, draft.apptEnd) : "—"], - ["Status", draft.status || "Incomplete"], + ["Status", draft.status || "Pending"], ]; } diff --git a/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary.tsx b/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary.tsx index e330f575..63529f73 100644 --- a/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary.tsx +++ b/src/app/(protected)/workorders/_components/wizard/wizard-sidebar-summary.tsx @@ -8,9 +8,9 @@ import { ColorDot } from "@/app/(protected)/workorders/_components/wizard/wizard export function WizardSidebarSummary({ draft }: { draft: WorkOrderWizardDraft }) { const summary = buildWizardSidebarSummaryRows(draft); - const statusLabel = draft.status || "Incomplete"; + const statusLabel = draft.status || "Pending"; const statusValue = statusLabel as WizardWOStatus; - const statusDotColor = WIZARD_STATUS_DOTS[statusValue] ?? WIZARD_STATUS_DOTS.Incomplete; + const statusDotColor = WIZARD_STATUS_DOTS[statusValue] ?? WIZARD_STATUS_DOTS.Pending; return (
diff --git a/src/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time.tsx b/src/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time.tsx index 208bb513..5f386d20 100644 --- a/src/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time.tsx +++ b/src/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time.tsx @@ -194,8 +194,8 @@ export function WizardStepVendorTime({ draft.technicianAssigned === false ? undefined : vendors.find((v) => String(v.id) === draft.vendorId); - const statusValue = (draft.status || "Incomplete") as WizardWOStatus; - const statusDotColor = WIZARD_STATUS_DOTS[statusValue] ?? WIZARD_STATUS_DOTS.Incomplete; + const statusValue = (draft.status || "Pending") as WizardWOStatus; + const statusDotColor = WIZARD_STATUS_DOTS[statusValue] ?? WIZARD_STATUS_DOTS.Pending; const selectedDistance = formatVendorDistance(selectedVendor?.distanceMiles); const closabilityGaps = getClosabilityGaps(wizardDraftToClosabilityInput(draft)); diff --git a/src/app/(protected)/workorders/_hooks/use-work-orders-table-ui-state.ts b/src/app/(protected)/workorders/_hooks/use-work-orders-table-ui-state.ts index 196bfe69..da2bf21b 100644 --- a/src/app/(protected)/workorders/_hooks/use-work-orders-table-ui-state.ts +++ b/src/app/(protected)/workorders/_hooks/use-work-orders-table-ui-state.ts @@ -60,7 +60,7 @@ export function useWorkOrdersTableUiState(weekMonday: string) { setDraft({ ...EMPTY_TABLE_DRAFT, scheduledOn, - status: scheduledOn ? "Scheduled" : "Incomplete", + status: scheduledOn ? "Scheduled" : "Pending", }); }, [weekMonday], diff --git a/src/domain/work-orders/mappers/work-order-board-mapper.ts b/src/domain/work-orders/mappers/work-order-board-mapper.ts index f1f046f9..4e837c84 100644 --- a/src/domain/work-orders/mappers/work-order-board-mapper.ts +++ b/src/domain/work-orders/mappers/work-order-board-mapper.ts @@ -8,11 +8,7 @@ import { WORK_ORDER_TYPE_API, } from "@/domain/work-orders/types/work-order-board"; -import type { - WizardWOStatus, - WOType, - WorkOrderWizardDraft, -} from "@/domain/work-orders/types/work-order-wizard"; +import type { WOType, WorkOrderWizardDraft } from "@/domain/work-orders/types/work-order-wizard"; import { fmtDateRange } from "@/domain/work-orders/utils/wizard-date-utils"; @@ -20,6 +16,7 @@ import { assignWizardScheduleFields } from "@/domain/work-orders/mappers/assign- import { assignWizardVendorApptFields } from "@/domain/work-orders/mappers/assign-wizard-vendor-appt-fields"; import { assignWizardServicePocFields } from "@/domain/work-orders/mappers/assign-wizard-service-poc-fields"; import { resolveIsAddOnForCreate } from "@/domain/work-orders/utils/wo-addon-cutoff"; +import { resolveCreationStatus } from "@/domain/work-orders/utils/wo-lifecycle-transitions"; const WO_TYPE_TO_API: Record = { PM: WORK_ORDER_TYPE_API.PM, @@ -114,7 +111,7 @@ export function mapWizardDraftToBoardCreatePayload( }; if (draft.status) { - payload.lifecycleStatus = LIFECYCLE_STATUS_API[draft.status as WizardWOStatus]; + payload.lifecycleStatus = LIFECYCLE_STATUS_API[resolveCreationStatus(draft)]; } if (draft.woNumber.trim()) { diff --git a/src/domain/work-orders/types/work-order-table-row.ts b/src/domain/work-orders/types/work-order-table-row.ts index 9b973ebf..2e2c4464 100644 --- a/src/domain/work-orders/types/work-order-table-row.ts +++ b/src/domain/work-orders/types/work-order-table-row.ts @@ -175,7 +175,7 @@ export const EMPTY_TABLE_DRAFT: WorkOrderTableDraft = { techPhone: "", apptStart: "", apptEnd: "", - status: "Incomplete", + status: "Pending", pocName: "", pocPhone: "", pocNotes: "", diff --git a/src/domain/work-orders/types/work-order-wizard.ts b/src/domain/work-orders/types/work-order-wizard.ts index 3a3416e1..ae2b3ff3 100644 --- a/src/domain/work-orders/types/work-order-wizard.ts +++ b/src/domain/work-orders/types/work-order-wizard.ts @@ -109,7 +109,7 @@ export const EMPTY_WIZARD_DRAFT: WorkOrderWizardDraft = { vendorNotes: "", apptStart: "", apptEnd: "", - status: "Incomplete", + status: "Pending", pocName: "", pocPhone: "", pocNotes: "", diff --git a/src/domain/work-orders/utils/wo-lifecycle-transitions.ts b/src/domain/work-orders/utils/wo-lifecycle-transitions.ts index bbef896a..0a5a0064 100644 --- a/src/domain/work-orders/utils/wo-lifecycle-transitions.ts +++ b/src/domain/work-orders/utils/wo-lifecycle-transitions.ts @@ -38,6 +38,8 @@ export const CREATION_INLINE_STATUSES: readonly WizardWOStatus[] = [ export const SCHEDULED_NEEDS_DATE_MSG = "Set a Schedule On date before marking this work order as Scheduled."; +export const INCOMPLETE_NEEDS_DATE_MSG = + "Set a Schedule On date before marking this work order as Incomplete."; export const PENDING_NEEDS_NO_DATE_MSG = "Clear the Schedule On date before marking this work order as Pending."; @@ -134,6 +136,9 @@ export function getStatusOptionState( status: WizardWOStatus, closabilityGaps: string[], ): StatusOptionState { + if (status === "Incomplete" && !hasConcreteScheduleDate(row)) { + return { disabled: true, title: INCOMPLETE_NEEDS_DATE_MSG }; + } if (status === "Pending" && hasConcreteScheduleDate(row)) { return { disabled: true, title: PENDING_NEEDS_NO_DATE_MSG }; } @@ -211,5 +216,8 @@ export function resolveCreationStatus(row: ScheduleDateInput & { status: string if (autoStatus === "Scheduled" || autoStatus === "Pending") { return autoStatus; } - return (row.status || "Incomplete") as WizardWOStatus; + if (!row.status || (row.status === "Incomplete" && !hasConcreteScheduleDate(row))) { + return "Pending"; + } + return row.status as WizardWOStatus; } diff --git a/src/test/domain/work-orders/mappers/work-order-board-mapper.test.ts b/src/test/domain/work-orders/mappers/work-order-board-mapper.test.ts index cb5dca07..a9d41ed6 100644 --- a/src/test/domain/work-orders/mappers/work-order-board-mapper.test.ts +++ b/src/test/domain/work-orders/mappers/work-order-board-mapper.test.ts @@ -61,7 +61,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => { isAddOn: false, - lifecycleStatus: 1, + lifecycleStatus: 2, }); }); @@ -283,7 +283,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => { expect(payload.scheduledDate).toBeUndefined(); }); - it("keeps Incomplete on week-only create and omits scheduledDate", () => { + it("normalizes Incomplete to Pending on week-only create and omits scheduledDate", () => { const payload = mapWizardDraftToBoardCreatePayload({ ...EMPTY_WIZARD_DRAFT, type: "PM", @@ -293,7 +293,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => { targetWeek: "2026-06-22", }); - expect(payload.lifecycleStatus).toBe(LIFECYCLE_STATUS_API.Incomplete); + expect(payload.lifecycleStatus).toBe(LIFECYCLE_STATUS_API.Pending); expect(payload.scheduleWeekOnly).toBe(true); expect(payload.targetWeek).toBe("2026-06-22"); expect(payload.scheduledDate).toBeUndefined();