@@ -138,10 +141,11 @@ export function WizardStepTypeSchedule({
WO Number
onUpdate("woNumber", e.target.value)}
+ onChange={(e) => onUpdate("woNumber", e.target.value.replace(/\D/g, "").slice(0, 20))}
onBlur={() => onDuplicateWoNumber?.(draft.woNumber)}
- placeholder="e.g. 24818"
+ placeholder="e.g. 12345678901"
maxLength={20}
className={DLG_INPUT_CLS}
style={DLG_INPUT_STYLE}
@@ -154,13 +158,17 @@ export function WizardStepTypeSchedule({
value={draft.assigneeId}
placeholder="Select…"
icon={
-
+ selectedUser ? (
+
+ ) : (
+
+ )
}
searchPlaceholder="Search dispatcher…"
options={users.map((u) => ({
key: String(u.id),
label: u.name,
- left: ,
+ left: ,
}))}
onPick={(id) => {
const user = users.find((u) => String(u.id) === id);
@@ -177,8 +185,15 @@ export function WizardStepTypeSchedule({
onPatch({ scheduledOn: "", scheduleWeekOnly: false })
+ draft.scheduledOn !== "" || draft.scheduleWeekOnly || draft.scheduleEnd
+ ? () =>
+ onPatch({
+ scheduledOn: "",
+ scheduleWeekOnly: false,
+ scheduleEnd: "",
+ schedMode: undefined,
+ targetWeek: "",
+ })
: undefined
}
>
@@ -186,11 +201,38 @@ export function WizardStepTypeSchedule({
onPatch({ scheduledOn: iso, scheduleWeekOnly: false })}
- onChangeWeek={(w) => onPatch({ scheduledOn: w, scheduleWeekOnly: Boolean(w) })}
+ scheduleEnd={draft.scheduleEnd}
+ schedMode={draft.schedMode}
+ onChange={(iso) =>
+ onPatch({
+ scheduledOn: iso,
+ scheduleWeekOnly: false,
+ scheduleEnd: "",
+ schedMode: "date",
+ targetWeek: "",
+ })
+ }
+ onChangeWeek={(w) =>
+ onPatch({
+ scheduledOn: w,
+ scheduleWeekOnly: Boolean(w),
+ scheduleEnd: "",
+ schedMode: "week",
+ targetWeek: w,
+ })
+ }
+ onChangeRange={(s, e) =>
+ onPatch({
+ scheduledOn: s,
+ scheduleEnd: e,
+ schedMode: "range",
+ scheduleWeekOnly: false,
+ targetWeek: "",
+ })
+ }
/>
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 d41c939a..7dbcb199 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
@@ -1,21 +1,21 @@
-import { Clock, ExternalLink, Mail, Wrench } from "lucide-react";
+import { Clock, ExternalLink, Mail, User, Wrench } from "lucide-react";
import { Text } from "@/components/ui/text";
import type { VendorDropdownItem } from "@/domain/work-orders/types/work-order";
import {
- ALL_WIZARD_STATUSES,
TIME_SLOTS,
- WIZARD_STATUS_DOTS,
- type WizardWOStatus,
type WorkOrderWizardDraft,
} from "@/domain/work-orders/types/work-order-wizard";
import { calcDuration, fmt12 } from "@/domain/work-orders/utils/wizard-date-utils";
+import {
+ formatVendorDistance,
+ formatVendorTechnicianLabel,
+} from "@/domain/work-orders/utils/vendor-dropdown-label";
import { WizardFieldSelect } from "@/app/(protected)/workorders/_components/wizard/wizard-field-select";
import {
DLG_INPUT_CLS,
DLG_INPUT_STYLE,
} from "@/app/(protected)/workorders/_components/wizard/wizard-input-styles";
import {
- ColorDot,
Detail,
WizLabel,
WizLabelRow,
@@ -33,11 +33,13 @@ function WizardVendorDetail({
vendor,
techPhone,
vendorNotes,
+ distance,
onUpdate,
}: {
vendor: VendorDropdownItem;
techPhone: string;
vendorNotes: string;
+ distance: string;
onUpdate:
(key: K, value: WorkOrderWizardDraft[K]) => void;
}) {
return (
@@ -61,9 +63,20 @@ function WizardVendorDetail({
border: "1px solid var(--color-border)",
}}
>
-
- {vendor.companyName || "—"}
+
+
+ {vendor.companyName || "—"}
+
+ {Boolean(distance) && (
+
+ {distance}
+
+ )}
+ {Boolean(vendor.contactName) &&
}
+ {Boolean(vendor.tradeSpecialties) && (
+
+ )}
{Boolean(vendor.address) &&
}
{Boolean(vendor.address) && (
String(v.id) === draft.vendorId);
- const statusValue = (draft.status || "Incomplete") as WizardWOStatus;
- const statusDotColor = WIZARD_STATUS_DOTS[statusValue] ?? WIZARD_STATUS_DOTS.Incomplete;
+ const selectedDistance = formatVendorDistance(selectedVendor?.distanceMiles);
return (
@@ -133,7 +145,9 @@ export function WizardStepVendorTime({
color: "var(--color-text-secondary)",
}}
>
- {selectedVendor.companyName.slice(0, 2).toUpperCase()}
+ {(selectedVendor.contactName || selectedVendor.companyName)
+ .slice(0, 2)
+ .toUpperCase()}
) : (
@@ -142,7 +156,7 @@ export function WizardStepVendorTime({
searchPlaceholder="Search technician…"
options={vendors.map((v) => ({
key: String(v.id),
- label: v.companyName,
+ label: formatVendorTechnicianLabel(v),
}))}
onPick={(id) => {
const vendor = vendors.find((v) => String(v.id) === id);
@@ -160,6 +174,7 @@ export function WizardStepVendorTime({
vendor={selectedVendor}
techPhone={draft.techPhone}
vendorNotes={draft.vendorNotes}
+ distance={selectedDistance}
onUpdate={onUpdate}
/>
)}
@@ -213,22 +228,6 @@ export function WizardStepVendorTime({
)}
-
-
- Status
- }
- options={ALL_WIZARD_STATUSES.map((s) => ({
- key: s,
- label: s,
- left: ,
- }))}
- onPick={(s) => onUpdate("status", s as WizardWOStatus)}
- />
-
);
}
diff --git a/src/app/(protected)/workorders/_components/work-order-form.tsx b/src/app/(protected)/workorders/_components/work-order-form.tsx
index 35e3afa7..eddb9511 100644
--- a/src/app/(protected)/workorders/_components/work-order-form.tsx
+++ b/src/app/(protected)/workorders/_components/work-order-form.tsx
@@ -3,8 +3,9 @@ import { useQuery } from "@tanstack/react-query";
import { useForm, useWatch } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Link as RouterLink, useNavigate, useParams, useSearchParams } from "react-router";
-import { Box, Breadcrumbs, Button, CircularProgress, Link, Paper, Stack } from "@mui/material";
+import { Box, Breadcrumbs, Button, Link, Paper, Stack } from "@mui/material";
import { Text } from "@/components/ui/text";
+import { QueryErrorPanel } from "@/components/ui/query-error-panel";
import { vendorOperationsApi } from "@/domain/vendor-operations/api/vendor-operations-api";
import { useDropdownOptionsByCategory } from "@/domain/settings/dropdown-options/use-cases/use-dropdown-options-by-category";
import { mapWorkOrderDetailToFormValues } from "@/domain/work-orders/mappers/work-order-mapper";
@@ -28,6 +29,7 @@ import {
WorkOrderDetailsFields,
} from "@/app/(protected)/workorders/_components/work-order-fields";
import { VendorAndTimeSection } from "@/app/(protected)/workorders/_components/vendor-assignment-section";
+import { DetailPageSkeleton } from "@/app/(protected)/workorders/_components/loading/detail-page-skeleton";
type ScheduleBounds = {
kind: "valid" | "invalid" | "open";
@@ -125,7 +127,12 @@ function useWorkOrderFormState() {
const isEdit = Boolean(id);
const assignVendorRequested = searchParams.get("assignVendor") === "1";
- const { data: detail, isLoading: isLoadingDetail, error: detailError } = useWorkOrderDetail(id);
+ const {
+ data: detail,
+ isLoading: isLoadingDetail,
+ error: detailError,
+ refetch: refetchDetail,
+ } = useWorkOrderDetail(id);
const { data: locations = [], isLoading: isLoadingLocations } = useWorkOrderLocations();
const { data: employees = [] } = useWorkOrderEmployeesDropdown();
const { data: problems = [] } = useDropdownOptionsByCategory("Problem");
@@ -225,6 +232,7 @@ function useWorkOrderFormState() {
detail,
isLoading,
detailError,
+ refetchDetail,
isSaving: saveMutation.isPending,
register,
control,
@@ -264,6 +272,7 @@ export default function WorkOrderFormPage() {
detail,
isLoading,
detailError,
+ refetchDetail,
isSaving,
register,
control,
@@ -296,17 +305,16 @@ export default function WorkOrderFormPage() {
} = useWorkOrderFormState();
if (isLoading) {
- return (
-
-
-
- );
+ return ;
}
if (detailError) {
return (
- Unable to load this work order. Please try again.
+ void refetchDetail()}
+ />
);
}
diff --git a/src/domain/work-orders/mappers/assign-wizard-schedule-fields.ts b/src/domain/work-orders/mappers/assign-wizard-schedule-fields.ts
index c47021a3..3c4cd207 100644
--- a/src/domain/work-orders/mappers/assign-wizard-schedule-fields.ts
+++ b/src/domain/work-orders/mappers/assign-wizard-schedule-fields.ts
@@ -2,7 +2,11 @@ import type { WorkOrderBoardCreatePayload } from "@/domain/work-orders/types/wor
import type { WorkOrderWizardDraft } from "@/domain/work-orders/types/work-order-wizard";
import { mondayOf } from "@/domain/work-orders/utils/wizard-date-utils";
-/** Mutates `payload` with `dueDate` and day/week schedule fields (range mode has no schedule fields). */
+/**
+ * Mutates `payload` with `dueDate` and schedule fields.
+ * Range mode lands on the board using the range start as `scheduledDate`
+ * (prototype `hasScheduleDate`: a range start qualifies as scheduled).
+ */
export function assignWizardScheduleFields(
payload: WorkOrderBoardCreatePayload,
draft: WorkOrderWizardDraft,
@@ -21,7 +25,7 @@ export function assignWizardScheduleFields(
payload.scheduleWeekOnly = true;
payload.targetWeek = week;
}
- } else if (!isRange && draft.scheduledOn) {
+ } else if (draft.scheduledOn && (isRange || !draft.scheduleWeekOnly)) {
payload.scheduledDate = draft.scheduledOn;
}
}
diff --git a/src/domain/work-orders/mappers/assign-wizard-service-poc-fields.ts b/src/domain/work-orders/mappers/assign-wizard-service-poc-fields.ts
index 66d906bd..cdac7c9b 100644
--- a/src/domain/work-orders/mappers/assign-wizard-service-poc-fields.ts
+++ b/src/domain/work-orders/mappers/assign-wizard-service-poc-fields.ts
@@ -7,42 +7,7 @@ function trimOrUndefined(value: string | undefined): string | undefined {
return trimmed ? trimmed : undefined;
}
-function normalizeExtraServices(
- primary: string | undefined,
- extras: string[],
-): string[] | undefined {
- if (extras.length === 0) {
- return undefined;
- }
-
- const seen = new Set();
-
- const primaryKey = primary?.toLowerCase() ?? "";
-
- const out: string[] = [];
-
- for (const raw of extras) {
- const trimmed = raw.trim();
-
- if (!trimmed) {
- continue;
- }
-
- const key = trimmed.toLowerCase();
-
- if (key === primaryKey || seen.has(key)) {
- continue;
- }
-
- seen.add(key);
-
- out.push(trimmed);
- }
-
- return out.length > 0 ? out : undefined;
-}
-
-/** Mutates `payload` with primary/extra services, service notes, POC, tech phone, and vendor notes. */
+/** Mutates `payload` with primary service, service notes, POC, tech phone, and vendor notes. */
export function assignWizardServicePocFields(
payload: WorkOrderBoardCreatePayload,
draft: WorkOrderWizardDraft,
@@ -53,12 +18,6 @@ export function assignWizardServicePocFields(
payload.primaryService = primaryService;
}
- const extraServices = normalizeExtraServices(primaryService, draft.extraServices);
-
- if (extraServices) {
- payload.extraServices = extraServices;
- }
-
const serviceNotes = trimOrUndefined(draft.pmNote);
if (serviceNotes) {
diff --git a/src/test/app/(protected)/workorders/new-wo-wizard-duplicate.test.tsx b/src/test/app/(protected)/workorders/new-wo-wizard-duplicate.test.tsx
index e1e6acb5..32f76148 100644
--- a/src/test/app/(protected)/workorders/new-wo-wizard-duplicate.test.tsx
+++ b/src/test/app/(protected)/workorders/new-wo-wizard-duplicate.test.tsx
@@ -15,10 +15,13 @@ vi.mock("@/domain/work-orders/use-cases/use-create-work-order-from-wizard", () =
}));
vi.mock("@/domain/work-orders/use-cases/use-work-order-detail", () => ({
- useWorkOrderLocations: () => ({ data: [] }),
useWorkOrderVendors: () => ({ data: [] }),
}));
+vi.mock("@/domain/locations/use-cases/use-location-sites", () => ({
+ useLocationSites: () => ({ data: [] }),
+}));
+
vi.mock("@/domain/locations/use-cases/use-location-detail", () => ({
useLocationDetail: () => ({ data: undefined }),
}));
@@ -45,7 +48,7 @@ describe("NewWoWizard duplicate wo number", () => {
/>,
);
- const woNumberInput = screen.getByPlaceholderText("e.g. 24818");
+ const woNumberInput = screen.getByPlaceholderText("e.g. 12345678901");
fireEvent.change(woNumberInput, {
target: { value: "12345678901" },
});
@@ -74,7 +77,7 @@ describe("NewWoWizard duplicate wo number", () => {
/>,
);
- const woNumberInput = screen.getByPlaceholderText("e.g. 24818");
+ const woNumberInput = screen.getByPlaceholderText("e.g. 12345678901");
fireEvent.change(woNumberInput, {
target: { value: "98765432109" },
});
diff --git a/src/test/app/(protected)/workorders/use-wizard-poc-autofill.test.tsx b/src/test/app/(protected)/workorders/use-wizard-poc-autofill.test.tsx
new file mode 100644
index 00000000..5f9113b8
--- /dev/null
+++ b/src/test/app/(protected)/workorders/use-wizard-poc-autofill.test.tsx
@@ -0,0 +1,78 @@
+import { act, renderHook } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { useWizardPocAutofill } from "@/app/(protected)/workorders/_components/wizard/use-wizard-poc-autofill";
+import type { Location } from "@/domain/locations/types/location";
+import {
+ EMPTY_WIZARD_DRAFT,
+ type WorkOrderWizardDraft,
+} from "@/domain/work-orders/types/work-order-wizard";
+import { useState } from "react";
+
+function baseLocation(overrides: Partial = {}): Location {
+ return {
+ id: "loc-1",
+ name: "BK5",
+ contact: "Janelle Pickett",
+ phone: "214-555-0111",
+ ...overrides,
+ } as Location;
+}
+
+describe("useWizardPocAutofill", () => {
+ it("fills empty POC fields from location detail once", () => {
+ const { result } = renderHook(() => {
+ const [draft, setDraft] = useState({ ...EMPTY_WIZARD_DRAFT });
+ useWizardPocAutofill(true, "loc-1", baseLocation(), setDraft);
+ return draft;
+ });
+
+ expect(result.current.pocName).toBe("Janelle Pickett");
+ expect(result.current.pocPhone).toBe("214-555-0111");
+ });
+
+ it("does not overwrite POC edits made before location detail arrives", () => {
+ const { result, rerender } = renderHook(
+ ({ detail }: { detail: Location | undefined }) => {
+ const [draft, setDraft] = useState({
+ ...EMPTY_WIZARD_DRAFT,
+ pocName: "Dispatcher Typed",
+ pocPhone: "999-000-1111",
+ });
+ useWizardPocAutofill(true, "loc-1", detail, setDraft);
+ return draft;
+ },
+ { initialProps: { detail: undefined as Location | undefined } },
+ );
+
+ expect(result.current.pocName).toBe("Dispatcher Typed");
+
+ act(() => {
+ rerender({ detail: baseLocation() });
+ });
+
+ expect(result.current.pocName).toBe("Dispatcher Typed");
+ expect(result.current.pocPhone).toBe("999-000-1111");
+ });
+
+ it("re-seeds POC after re-selecting the same location clears the fields", () => {
+ const { result } = renderHook(() => {
+ const [draft, setDraft] = useState({ ...EMPTY_WIZARD_DRAFT });
+ const autofill = useWizardPocAutofill(true, "loc-1", baseLocation(), setDraft);
+ return { draft, setDraft, autofill };
+ });
+
+ expect(result.current.draft.pocName).toBe("Janelle Pickett");
+
+ act(() => {
+ result.current.setDraft((current) => ({
+ ...current,
+ pocName: "",
+ pocPhone: "",
+ }));
+ result.current.autofill.notifyLocationChanged("loc-1");
+ });
+
+ expect(result.current.draft.pocName).toBe("Janelle Pickett");
+ expect(result.current.draft.pocPhone).toBe("214-555-0111");
+ });
+});
diff --git a/src/test/app/(protected)/workorders/wizard-schedule-date-range.test.tsx b/src/test/app/(protected)/workorders/wizard-schedule-date-range.test.tsx
new file mode 100644
index 00000000..7ef8223c
--- /dev/null
+++ b/src/test/app/(protected)/workorders/wizard-schedule-date-range.test.tsx
@@ -0,0 +1,110 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+import { WizardStepTypeSchedule } from "@/app/(protected)/workorders/_components/wizard/wizard-step-type-schedule";
+import {
+ EMPTY_WIZARD_DRAFT,
+ type WorkOrderWizardDraft,
+} from "@/domain/work-orders/types/work-order-wizard";
+import { pad2, todayIso } from "@/domain/work-orders/utils/wizard-date-utils";
+
+function baseDraft(overrides: Partial = {}): WorkOrderWizardDraft {
+ return { ...EMPTY_WIZARD_DRAFT, type: "PM", ...overrides };
+}
+
+function currentMonthIso(day: number): string {
+ const [y, m] = todayIso().split("-").map(Number);
+ return `${y}-${pad2(m)}-${pad2(day)}`;
+}
+
+async function openScheduleRangePicker() {
+ fireEvent.click(screen.getByRole("button", { name: /pick a date/i }));
+ const rangeTab = await screen.findByRole("button", { name: "Range" });
+ fireEvent.click(rangeTab);
+}
+
+describe("WizardStepTypeSchedule — Schedule On range selection", () => {
+ it("clicks start then end in order and submits schedMode range with matching dates", async () => {
+ const onUpdate = vi.fn();
+ const onPatch = vi.fn();
+
+ render(
+ ,
+ );
+
+ await openScheduleRangePicker();
+
+ const startIso = currentMonthIso(5);
+ const endIso = currentMonthIso(20);
+
+ fireEvent.click(screen.getByRole("button", { name: "5" }));
+ fireEvent.click(screen.getByRole("button", { name: "20" }));
+ fireEvent.click(screen.getByRole("button", { name: /^done$/i }));
+
+ expect(onPatch).toHaveBeenCalledWith({
+ scheduledOn: startIso,
+ scheduleEnd: endIso,
+ schedMode: "range",
+ scheduleWeekOnly: false,
+ targetWeek: "",
+ });
+ });
+
+ it("normalizes an out-of-order click (end clicked before start) into start {
+ const onUpdate = vi.fn();
+ const onPatch = vi.fn();
+
+ render(
+ ,
+ );
+
+ await openScheduleRangePicker();
+
+ const laterIso = currentMonthIso(20);
+ const earlierIso = currentMonthIso(5);
+
+ // User clicks the later date first, then an earlier date — the field must
+ // normalize this into (start = earlier, end = later) before submission.
+ fireEvent.click(screen.getByRole("button", { name: "20" }));
+ fireEvent.click(screen.getByRole("button", { name: "5" }));
+ fireEvent.click(screen.getByRole("button", { name: /^done$/i }));
+
+ expect(onPatch).toHaveBeenCalledWith({
+ scheduledOn: earlierIso,
+ scheduleEnd: laterIso,
+ schedMode: "range",
+ scheduleWeekOnly: false,
+ targetWeek: "",
+ });
+ });
+
+ it("does not submit until both a start and end date are picked", async () => {
+ const onUpdate = vi.fn();
+ const onPatch = vi.fn();
+
+ render(
+ ,
+ );
+
+ await openScheduleRangePicker();
+
+ fireEvent.click(screen.getByRole("button", { name: "5" }));
+
+ expect(screen.getByRole("button", { name: /^done$/i })).toBeDisabled();
+ expect(onPatch).not.toHaveBeenCalled();
+ });
+});
diff --git a/src/test/app/(protected)/workorders/wizard-service-clears-vendor.test.tsx b/src/test/app/(protected)/workorders/wizard-service-clears-vendor.test.tsx
new file mode 100644
index 00000000..3812fb63
--- /dev/null
+++ b/src/test/app/(protected)/workorders/wizard-service-clears-vendor.test.tsx
@@ -0,0 +1,88 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+import { WizardStepLocationServiceSelect } from "@/app/(protected)/workorders/_components/wizard/wizard-step-location-service-select";
+import {
+ EMPTY_WIZARD_DRAFT,
+ type WorkOrderWizardDraft,
+} from "@/domain/work-orders/types/work-order-wizard";
+
+describe("WizardStepLocationServiceSelect — vendor clear on service change", () => {
+ it("clears vendor fields when the primary service changes", () => {
+ const onPatch = vi.fn();
+ const draft: WorkOrderWizardDraft = {
+ ...EMPTY_WIZARD_DRAFT,
+ pm: "HVAC",
+ vendorId: "9",
+ vendorName: "Old Vendor",
+ techPhone: "555-0100",
+ };
+
+ render(
+ ,
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "HVAC" }));
+ fireEvent.click(screen.getByRole("button", { name: "Plumbing" }));
+
+ expect(onPatch).toHaveBeenCalledWith(
+ expect.objectContaining({
+ pm: "Plumbing",
+ extraServices: [],
+ vendorId: "",
+ vendorName: "",
+ techPhone: "",
+ }),
+ );
+ });
+
+ it("replaces the selected service in Service & Notes without persisting extraServices", () => {
+ const onPatch = vi.fn();
+ const draft: WorkOrderWizardDraft = {
+ ...EMPTY_WIZARD_DRAFT,
+ pm: "HVAC",
+ extraServices: ["Plumbing"],
+ vendorId: "9",
+ vendorName: "Old Vendor",
+ techPhone: "555-0100",
+ };
+
+ render(
+ ,
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Electrical" }));
+
+ expect(onPatch).toHaveBeenCalledWith({
+ pm: "Electrical",
+ extraServices: [],
+ vendorId: "",
+ vendorName: "",
+ techPhone: "",
+ });
+ });
+});
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 5ecb9568..ad94b054 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
@@ -122,8 +122,6 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
primaryService: "HVAC PM",
- extraServices: ["Filter change", "Coil clean"],
-
serviceNotes: "Check unit on roof",
pocName: "Jane Site Lead",
@@ -141,6 +139,8 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
expect(payload.trade).toBeUndefined();
+ expect(payload.extraServices).toBeUndefined();
+
expect(payload.description).toBeUndefined();
expect(payload.scheduleWeekOnly).toBeUndefined();
@@ -269,7 +269,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
).toThrow("Site code is required");
});
- it("omits scheduledDate for range schedule and puts range in description only", () => {
+ it("sets scheduledDate from range start and keeps range text in description", () => {
const payload = mapWizardDraftToBoardCreatePayload({
...EMPTY_WIZARD_DRAFT,
@@ -288,7 +288,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
vendorNotes: "Also not in description",
});
- expect(payload.scheduledDate).toBeUndefined();
+ expect(payload.scheduledDate).toBe("2026-06-08");
expect(payload.scheduleWeekOnly).toBeUndefined();
@@ -309,7 +309,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
expect(payload.vendorNotes).toBe("Also not in description");
});
- it("maps service notes and extras as structured fields instead of description", () => {
+ it("maps service notes as structured fields and omits extraServices from wizard create", () => {
const payload = mapWizardDraftToBoardCreatePayload({
...EMPTY_WIZARD_DRAFT,
@@ -326,7 +326,7 @@ describe("mapWizardDraftToBoardCreatePayload", () => {
expect(payload.primaryService).toBe("HVAC PM");
- expect(payload.extraServices).toEqual(["Filter change", "Coil clean"]);
+ expect(payload.extraServices).toBeUndefined();
expect(payload.serviceNotes).toBe("Check unit on roof");