diff --git a/src/app/v/[token]/dispatch/_components/checklist-section.tsx b/src/app/v/[token]/dispatch/_components/checklist-section.tsx index 850c2b6d..4c1acb2e 100644 --- a/src/app/v/[token]/dispatch/_components/checklist-section.tsx +++ b/src/app/v/[token]/dispatch/_components/checklist-section.tsx @@ -22,10 +22,12 @@ export function ChecklistSection({ const toggle = (item: VendorPortalChecklistItem) => { if (locked) return; - updateItem.mutate( - { itemId: item.id, isCompleted: !item.isCompleted }, - { onSuccess: (updated) => onItemUpdated(updated) }, - ); + // mutateAsync resolves per call, unlike mutate's onSuccess which only fires for the + // latest call on this shared observer — needed so two quick toggles both report back. + void updateItem + .mutateAsync({ itemId: item.id, isCompleted: !item.isCompleted }) + .then((updated) => onItemUpdated(updated)) + .catch(() => undefined); }; if (!items.length) { diff --git a/src/test/app/v/checklist-section.test.tsx b/src/test/app/v/checklist-section.test.tsx index 2c853f7e..e0e1013e 100644 --- a/src/test/app/v/checklist-section.test.tsx +++ b/src/test/app/v/checklist-section.test.tsx @@ -67,4 +67,29 @@ describe("ChecklistSection", () => { await screen.findByText("Unable to update the checklist. Please try again."), ).toBeInTheDocument(); }); + + it("reports every successful toggle when two items are checked before the first responds", async () => { + const a: VendorPortalChecklistItem = { id: 1, itemText: "Check filters", isCompleted: false }; + const b: VendorPortalChecklistItem = { id: 2, itemText: "Check belts", isCompleted: false }; + const resolvers: Array<() => void> = []; + vi.spyOn(vendorPortalApi, "updateChecklistItem").mockImplementation( + (_token, _dispatchId, itemId) => + new Promise((resolve) => { + resolvers.push(() => resolve({ ...(itemId === 1 ? a : b), isCompleted: true })); + }), + ); + const onItemUpdated = vi.fn(); + renderSection({ items: [a, b] }, onItemUpdated); + + const [boxA, boxB] = screen.getAllByRole("checkbox"); + fireEvent.click(boxA); + fireEvent.click(boxB); + + await waitFor(() => expect(resolvers).toHaveLength(2)); + resolvers.forEach((resolve) => resolve()); + + await waitFor(() => + expect(onItemUpdated.mock.calls.map(([updated]) => updated.id)).toEqual([1, 2]), + ); + }); });