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 42537071..0b98083f 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 @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { toast } from "react-toastify"; import { isWoWizardMockEnabled } from "@/domain/work-orders/mocks/is-wo-wizard-mock-enabled"; import { @@ -46,6 +46,8 @@ export function useNewWoWizardState({ const [pocAutoFilledFor, setPocAutoFilledFor] = useState(""); const [duplicateRow, setDuplicateRow] = useState(null); const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false); + const draftWoNumberRef = useRef(draft.woNumber); + draftWoNumberRef.current = draft.woNumber; const { data: apiLocations = [] } = useWorkOrderLocations(); const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem"); @@ -125,7 +127,8 @@ export function useNewWoWizardState({ const handleDuplicateFound = (woNumber: string) => { void resolveDuplicate(woNumber).then((duplicate) => { - if (duplicate && woNumber === draft.woNumber) { + // Compare against the latest draft — ignore stale lookups after the user edits. + if (duplicate && woNumber === draftWoNumberRef.current) { setDuplicateRow(duplicate); } }); diff --git a/src/domain/work-orders/api/work-orders-api.ts b/src/domain/work-orders/api/work-orders-api.ts index e22cb9c3..417e2fe4 100644 --- a/src/domain/work-orders/api/work-orders-api.ts +++ b/src/domain/work-orders/api/work-orders-api.ts @@ -197,9 +197,9 @@ export const workOrdersApi = { return undefined; } - // `board/search` is fuzzy and paginated; exhaust pages until an exact WO# match appears. + // `board/search` is fuzzy and paginated (0-based); exhaust pages until an exact WO# match. const pageSize = 100; - let page = 1; + let page = 0; let scanned = 0; let totalCount = Number.POSITIVE_INFINITY; diff --git a/src/test/domain/work-orders/api/work-orders-api.test.ts b/src/test/domain/work-orders/api/work-orders-api.test.ts index 3d33441e..b7cec34b 100644 --- a/src/test/domain/work-orders/api/work-orders-api.test.ts +++ b/src/test/domain/work-orders/api/work-orders-api.test.ts @@ -306,7 +306,7 @@ describe("workOrdersApi.findByWoNumber", () => { }, ], totalCount: 1, - page: 1, + page: 0, pageSize: 100, }); @@ -321,7 +321,7 @@ describe("workOrdersApi.findByWoNumber", () => { const searchParams = apiGet.mock.calls[0]?.[1]?.searchParams as URLSearchParams; expect(Object.fromEntries(searchParams)).toEqual({ search: "10000001235", - page: "1", + page: "0", pageSize: "100", }); expect(result).toMatchObject({ id: 505, woNumber: "10000001235" }); @@ -336,7 +336,7 @@ describe("workOrdersApi.findByWoNumber", () => { lifecycleStatusLabel: "Incomplete", })), totalCount: 101, - page: 1, + page: 0, pageSize: 100, }) .mockResolvedValueOnce({ @@ -348,7 +348,7 @@ describe("workOrdersApi.findByWoNumber", () => { }, ], totalCount: 101, - page: 2, + page: 1, pageSize: 100, }); @@ -358,7 +358,7 @@ describe("workOrdersApi.findByWoNumber", () => { const secondParams = apiGet.mock.calls[1]?.[1]?.searchParams as URLSearchParams; expect(Object.fromEntries(secondParams)).toMatchObject({ search: "10000009999", - page: "2", + page: "1", pageSize: "100", }); expect(result).toMatchObject({ id: 999, woNumber: "10000009999" });