mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-01 05:03:13 +00:00
fix(work-orders): seed CompDoc address after location settles [SH-116]
This commit is contained in:
parent
bfc230d421
commit
cd4b8d27fd
2 changed files with 182 additions and 8 deletions
|
|
@ -46,22 +46,48 @@ export function useCompDocDialog({
|
|||
const [editDateCompleted, setEditDateCompleted] = useState("");
|
||||
const [editAddress, setEditAddress] = useState("");
|
||||
const seedKeyRef = useRef<string | null>(null);
|
||||
const addressSeededRef = useRef(false);
|
||||
const addressTouchedRef = useRef(false);
|
||||
|
||||
// Seed once per open/WO — row/detail refetches must not wipe in-progress edits.
|
||||
// Address waits for authoritative locationDetail (when a real location id exists)
|
||||
// and still accepts that first response without overwriting later user edits.
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
seedKeyRef.current = null;
|
||||
addressSeededRef.current = false;
|
||||
addressTouchedRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const key = String(row.id);
|
||||
if (seedKeyRef.current === key) return;
|
||||
seedKeyRef.current = key;
|
||||
setNotes(data?.notes ?? "");
|
||||
setDocState(docStateOf(row.docStatus));
|
||||
setGeneratedAt(data?.generatedAt ?? "");
|
||||
setEditDateCompleted(row.completedDate || "");
|
||||
if (seedKeyRef.current !== key) {
|
||||
seedKeyRef.current = key;
|
||||
addressSeededRef.current = false;
|
||||
addressTouchedRef.current = false;
|
||||
setNotes(data?.notes ?? "");
|
||||
setDocState(docStateOf(row.docStatus));
|
||||
setGeneratedAt(data?.generatedAt ?? "");
|
||||
setEditDateCompleted(row.completedDate || "");
|
||||
}
|
||||
|
||||
if (addressTouchedRef.current || addressSeededRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const awaitingLocation = Boolean(locId) && !isMockLocation && !locationDetail;
|
||||
if (awaitingLocation) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEditAddress(buildCompDocAddressLine(resolveCompDocSite(row, locationDetail)));
|
||||
}, [open, row, data?.notes, data?.generatedAt, locationDetail]);
|
||||
addressSeededRef.current = true;
|
||||
}, [open, row, data?.notes, data?.generatedAt, locationDetail, locId, isMockLocation]);
|
||||
|
||||
const handleAddressChange = (value: string) => {
|
||||
addressTouchedRef.current = true;
|
||||
setEditAddress(value);
|
||||
};
|
||||
|
||||
const amazonRep = row.pocName || "";
|
||||
const seaRep = row.tech || "";
|
||||
|
|
@ -118,7 +144,7 @@ export function useCompDocDialog({
|
|||
docState,
|
||||
generatedAt,
|
||||
editAddress,
|
||||
setEditAddress,
|
||||
setEditAddress: handleAddressChange,
|
||||
editDateCompleted,
|
||||
setEditDateCompleted,
|
||||
amazonRep,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
import { act, renderHook, waitFor } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ReactNode } from "react";
|
||||
import { useCompDocDialog } from "@/app/(protected)/workorders/_hooks/use-comp-doc-dialog";
|
||||
import type { Location } from "@/domain/locations/types/location";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
|
||||
const locationDetailState = vi.hoisted(() => ({
|
||||
data: undefined as Location | undefined,
|
||||
}));
|
||||
|
||||
vi.mock("@/domain/locations/use-cases/use-location-detail", () => ({
|
||||
useLocationDetail: () => ({ data: locationDetailState.data }),
|
||||
}));
|
||||
|
||||
function baseRow(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow {
|
||||
return {
|
||||
id: 42,
|
||||
woNumber: "WO-42",
|
||||
site: "SEA1",
|
||||
type: "PM",
|
||||
dispatcherId: "u1",
|
||||
dispatcherName: "Dispatcher",
|
||||
scheduledOn: "2026-06-01",
|
||||
completedDate: "",
|
||||
targetWeek: "",
|
||||
dayGroup: "",
|
||||
dayLabel: "",
|
||||
location: "Seattle",
|
||||
locationId: "loc-real-1",
|
||||
pm: "HVAC",
|
||||
serviceNotes: "",
|
||||
extraServices: [],
|
||||
vendorId: "",
|
||||
company: "Vendor Co",
|
||||
tech: "Tech One",
|
||||
techPhone: "",
|
||||
apptStart: "",
|
||||
apptEnd: "",
|
||||
apptTime: "",
|
||||
status: "Scheduled",
|
||||
docStatus: "No",
|
||||
pocName: "Amazon Rep",
|
||||
pocPhone: "",
|
||||
pocNotes: "",
|
||||
dueDate: "",
|
||||
rescheduleCount: 0,
|
||||
carriedOver: 0,
|
||||
originalWeek: "",
|
||||
originalDate: "",
|
||||
isPastDue: false,
|
||||
scheduleWeekOnly: false,
|
||||
mediaCount: 0,
|
||||
title: "PM — SEA1",
|
||||
priority: "Sev 3",
|
||||
primaryDispatchId: null,
|
||||
rowVersion: "",
|
||||
dispatchRowVersion: "",
|
||||
flagColor: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function wrapper({ children }: { children: ReactNode }) {
|
||||
const client = new QueryClient({
|
||||
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
|
||||
});
|
||||
return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
|
||||
}
|
||||
|
||||
describe("useCompDocDialog address seeding", () => {
|
||||
beforeEach(() => {
|
||||
locationDetailState.data = undefined;
|
||||
});
|
||||
|
||||
it("seeds address from the first authoritative locationDetail without locking on the empty fallback", async () => {
|
||||
const row = baseRow();
|
||||
const { result, rerender } = renderHook(
|
||||
() =>
|
||||
useCompDocDialog({
|
||||
row,
|
||||
open: true,
|
||||
onSave: vi.fn(),
|
||||
}),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
expect(result.current.editAddress).toBe("");
|
||||
|
||||
locationDetailState.data = {
|
||||
id: "loc-real-1",
|
||||
name: "SEA1",
|
||||
address: "3811 Distribution Dr",
|
||||
city: "Seattle",
|
||||
state: "WA",
|
||||
zipCode: "98101",
|
||||
} as Location;
|
||||
|
||||
rerender();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.editAddress).toContain("3811 Distribution Dr");
|
||||
});
|
||||
});
|
||||
|
||||
it("does not overwrite address after the dispatcher edits it", async () => {
|
||||
locationDetailState.data = {
|
||||
id: "loc-real-1",
|
||||
name: "SEA1",
|
||||
address: "3811 Distribution Dr",
|
||||
city: "Seattle",
|
||||
state: "WA",
|
||||
zipCode: "98101",
|
||||
} as Location;
|
||||
|
||||
const row = baseRow();
|
||||
const { result, rerender } = renderHook(
|
||||
() =>
|
||||
useCompDocDialog({
|
||||
row,
|
||||
open: true,
|
||||
onSave: vi.fn(),
|
||||
}),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.editAddress).toContain("3811 Distribution Dr");
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.setEditAddress("Dispatcher typed address");
|
||||
});
|
||||
|
||||
locationDetailState.data = {
|
||||
id: "loc-real-1",
|
||||
name: "SEA1",
|
||||
address: "999 Other St",
|
||||
city: "Seattle",
|
||||
state: "WA",
|
||||
zipCode: "98101",
|
||||
} as Location;
|
||||
rerender();
|
||||
|
||||
expect(result.current.editAddress).toBe("Dispatcher typed address");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue