mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
fix(work-orders): sync wizard refs in effects and exhaust duplicate WO lookup
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
db0b87eb8f
commit
c6c11b9f04
3 changed files with 50 additions and 11 deletions
|
|
@ -48,8 +48,14 @@ export function useNewWoWizardState({
|
||||||
const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false);
|
const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false);
|
||||||
const openRef = useRef(open);
|
const openRef = useRef(open);
|
||||||
const draftRef = useRef(draft);
|
const draftRef = useRef(draft);
|
||||||
openRef.current = open;
|
|
||||||
draftRef.current = draft;
|
useEffect(() => {
|
||||||
|
openRef.current = open;
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
draftRef.current = draft;
|
||||||
|
}, [draft]);
|
||||||
|
|
||||||
const { data: apiLocations = [] } = useWorkOrderLocations();
|
const { data: apiLocations = [] } = useWorkOrderLocations();
|
||||||
const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem");
|
const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem");
|
||||||
|
|
|
||||||
|
|
@ -193,20 +193,26 @@ export const workOrdersApi = {
|
||||||
|
|
||||||
findByWoNumber: async (woNumber: string): Promise<WorkOrderTableRow | undefined> => {
|
findByWoNumber: async (woNumber: string): Promise<WorkOrderTableRow | undefined> => {
|
||||||
const normalized = woNumber.trim();
|
const normalized = woNumber.trim();
|
||||||
// Skip empty / very short queries — fuzzy board/search would page endlessly for 1–2 chars.
|
// board/search contract: only send search when length >= 2.
|
||||||
const minLength = 3;
|
const minLength = 2;
|
||||||
const maxPages = 5;
|
// Safety cap — if hit before exhausting results, fail closed (do not treat as unique).
|
||||||
|
const safetyMaxPages = 50;
|
||||||
if (normalized.length < minLength) {
|
if (normalized.length < minLength) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// `board/search` is fuzzy and paginated (0-based); scan a bounded number of pages for an exact WO#.
|
// `board/search` is fuzzy and paginated (0-based); exhaust pages for an exact WO#.
|
||||||
const pageSize = 100;
|
const pageSize = 100;
|
||||||
let page = 0;
|
let page = 0;
|
||||||
let scanned = 0;
|
let scanned = 0;
|
||||||
let totalCount = Number.POSITIVE_INFINITY;
|
let totalCount = Number.POSITIVE_INFINITY;
|
||||||
|
|
||||||
while (scanned < totalCount && page < maxPages) {
|
while (scanned < totalCount) {
|
||||||
|
if (page >= safetyMaxPages) {
|
||||||
|
throw new Error(
|
||||||
|
"Unable to verify the work order number: search result set exceeded the safety page limit.",
|
||||||
|
);
|
||||||
|
}
|
||||||
const result = await workOrdersApi.searchBoard({
|
const result = await workOrdersApi.searchBoard({
|
||||||
search: normalized,
|
search: normalized,
|
||||||
page,
|
page,
|
||||||
|
|
|
||||||
|
|
@ -364,13 +364,13 @@ describe("workOrdersApi.findByWoNumber", () => {
|
||||||
expect(result).toMatchObject({ id: 999, woNumber: "10000009999" });
|
expect(result).toMatchObject({ id: 999, woNumber: "10000009999" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("skips remote search for short WO numbers", async () => {
|
it("skips remote search for single-character WO numbers", async () => {
|
||||||
const result = await workOrdersApi.findByWoNumber("12");
|
const result = await workOrdersApi.findByWoNumber("1");
|
||||||
expect(apiGet).not.toHaveBeenCalled();
|
expect(apiGet).not.toHaveBeenCalled();
|
||||||
expect(result).toBeUndefined();
|
expect(result).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("caps paging when scanning fuzzy board search results", async () => {
|
it("throws when the safety page limit is hit before exhausting results", async () => {
|
||||||
apiGet.mockResolvedValue({
|
apiGet.mockResolvedValue({
|
||||||
items: Array.from({ length: 100 }, (_, index) => ({
|
items: Array.from({ length: 100 }, (_, index) => ({
|
||||||
id: index + 1,
|
id: index + 1,
|
||||||
|
|
@ -382,9 +382,36 @@ describe("workOrdersApi.findByWoNumber", () => {
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await expect(workOrdersApi.findByWoNumber("10000005555")).rejects.toThrow(/safety page limit/i);
|
||||||
|
expect(apiGet).toHaveBeenCalledTimes(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns undefined after exhausting all fuzzy search pages", async () => {
|
||||||
|
apiGet
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
items: Array.from({ length: 100 }, (_, index) => ({
|
||||||
|
id: index + 1,
|
||||||
|
woNumber: `fuzzy-match-${index}`,
|
||||||
|
lifecycleStatusLabel: "Incomplete",
|
||||||
|
})),
|
||||||
|
totalCount: 150,
|
||||||
|
page: 0,
|
||||||
|
pageSize: 100,
|
||||||
|
})
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
items: Array.from({ length: 50 }, (_, index) => ({
|
||||||
|
id: index + 101,
|
||||||
|
woNumber: `fuzzy-match-${index + 100}`,
|
||||||
|
lifecycleStatusLabel: "Incomplete",
|
||||||
|
})),
|
||||||
|
totalCount: 150,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 100,
|
||||||
|
});
|
||||||
|
|
||||||
const result = await workOrdersApi.findByWoNumber("10000005555");
|
const result = await workOrdersApi.findByWoNumber("10000005555");
|
||||||
|
|
||||||
expect(apiGet).toHaveBeenCalledTimes(5);
|
expect(apiGet).toHaveBeenCalledTimes(2);
|
||||||
expect(result).toBeUndefined();
|
expect(result).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue