diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-detail.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-detail.png index cdea35c5..fb36ec63 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-detail.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-detail.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-empty.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-empty.png index d93b0653..e64d4c12 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-empty.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-empty.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-error.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-error.png index 48da2932..f07dbc15 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-error.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-error.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-filters.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-filters.png index 4a551b64..3a79d27a 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-filters.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-filters.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-list.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-list.png index 9d5372c7..a7109395 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-list.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-list.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-mobile.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-mobile.png index b014a299..6e98e3fa 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-mobile.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-mobile.png differ diff --git a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-new.png b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-new.png index 9d314c96..e6298c3f 100644 Binary files a/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-new.png and b/e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-new.png differ diff --git a/e2e/work-orders/board-day-pagination.spec.ts b/e2e/work-orders/board-day-pagination.spec.ts index 46f97a49..0a3cff18 100644 --- a/e2e/work-orders/board-day-pagination.spec.ts +++ b/e2e/work-orders/board-day-pagination.spec.ts @@ -30,6 +30,18 @@ function boardRow(id: number, woNumber: string, scheduledDate: string) { }; } +async function hideQueryDevtools(page: Page) { + await page.addStyleTag({ + content: + ".tsqd-parent-container { display: none !important; pointer-events: none !important; }", + }); + await page.locator(".tsqd-parent-container").evaluateAll((nodes) => { + for (const node of nodes) { + node.remove(); + } + }); +} + async function mockWorkOrderBoard(page: Page) { const wednesday = Array.from({ length: 60 }, (_, index) => boardRow(1000 + index, `WO-${1000 + index}`, "2026-08-19"), @@ -92,6 +104,7 @@ test.describe("work order per-day pagination (SH-241)", () => { }) => { const pager = page.getByTestId("wo-day-pagination"); await page.goto("/workorders"); + await hideQueryDevtools(page); await expect(page.getByRole("heading", { name: "Work Orders" })).toBeVisible({ timeout: 20_000, }); @@ -106,6 +119,7 @@ test.describe("work order per-day pagination (SH-241)", () => { await expect(page.getByTestId("wo-day-pagination-next")).toBeEnabled(); await expect(page.getByText("WO-1025")).toHaveCount(0); + await hideQueryDevtools(page); await page.getByTestId("wo-day-pagination-next").click(); await expect(pager.getByText("Page 2 of 3")).toBeVisible(); await expect(page.getByText("WO-1025").first()).toBeVisible(); diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table.tsx index 97ea625e..8af5b8b7 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table.tsx @@ -180,7 +180,7 @@ export function WoTable({ ); } - const emptyAdv = tableData.advActive && tableData.advResults.length === 0; + const emptyAdv = tableData.advActive && tableData.scopeTotalCount === 0; if (emptyAdv) { return ( diff --git a/src/app/(protected)/workorders/_hooks/use-work-orders-table-data.ts b/src/app/(protected)/workorders/_hooks/use-work-orders-table-data.ts index a43e2103..8f111937 100644 --- a/src/app/(protected)/workorders/_hooks/use-work-orders-table-data.ts +++ b/src/app/(protected)/workorders/_hooks/use-work-orders-table-data.ts @@ -161,10 +161,10 @@ export function useWorkOrdersTableData(filters: FiltersReturn) { pagination.setPageSize(next); }, goToPrevDayPage: advActive - ? () => filters.setPage(Math.max(0, filters.page - 1)) + ? () => filters.setPage(Math.max(0, pager.pageIndex - 1)) : pagination.goToPrevPage, goToNextDayPage: advActive - ? () => filters.setPage(Math.min(filters.page + 1, Math.max(0, pager.pageCount - 1))) + ? () => filters.setPage(Math.min(pager.pageIndex + 1, Math.max(0, pager.pageCount - 1))) : pagination.goToNextPage, revealScheduledRow: pagination.revealRow, }; diff --git a/src/domain/work-orders/utils/day-pagination.ts b/src/domain/work-orders/utils/day-pagination.ts index e828fa91..74d34c3b 100644 --- a/src/domain/work-orders/utils/day-pagination.ts +++ b/src/domain/work-orders/utils/day-pagination.ts @@ -116,7 +116,7 @@ export function pickBoardPager(input: { return { show: shouldShowSearchPagination({ isLoading: input.isLoading, - hasResults: input.advResultCount > 0, + hasResults: input.search.totalCount > 0, }), ...resolveSearchPager(input.search), footerLabel: SEARCH_PAGER_FOOTER_LABEL, diff --git a/src/test/app/(protected)/workorders/wo-table-adv-search-pagination.test.tsx b/src/test/app/(protected)/workorders/wo-table-adv-search-pagination.test.tsx index 6b9eac5a..496fa5d5 100644 --- a/src/test/app/(protected)/workorders/wo-table-adv-search-pagination.test.tsx +++ b/src/test/app/(protected)/workorders/wo-table-adv-search-pagination.test.tsx @@ -127,7 +127,7 @@ function tableData( } as ReturnTypeOfUseWorkOrdersTableData; } -describe("WoTable advanced-search pagination (SH-165)", () => { +describe("WoTable advanced-search pagination", () => { it("pages the flat Unassigned search without a pin or a 1778-row dump", () => { const goToNextDayPage = vi.fn(); const data = tableData({ goToNextDayPage }); @@ -160,4 +160,41 @@ describe("WoTable advanced-search pagination (SH-165)", () => { expect(screen.getByRole("button", { name: "Next page" })).toBeEnabled(); expect(screen.getByRole("button", { name: "Previous page" })).toBeDisabled(); }); + + it("keeps the search pager when the current page is empty but matches remain", () => { + const goToPrevDayPage = vi.fn(); + const data = tableData({ + rows: [], + advResults: [], + totalCount: 0, + scopeTotalCount: 1778, + dayPageIndex: 35, + dayPageCount: 36, + goToPrevDayPage, + }); + + renderWithProviders( + , + { withAuth: false }, + ); + + expect(screen.queryByText("No work orders match these filters")).not.toBeInTheDocument(); + expect(screen.getByText("RESULTS · 1778 items")).toBeInTheDocument(); + expect(screen.getByText("Page 36 of 36")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Previous page" })).toBeEnabled(); + + fireEvent.click(screen.getByRole("button", { name: "Previous page" })); + expect(goToPrevDayPage).toHaveBeenCalled(); + }); }); diff --git a/src/test/domain/work-orders/utils/day-pagination.test.ts b/src/test/domain/work-orders/utils/day-pagination.test.ts index 41664364..75d0e8c1 100644 --- a/src/test/domain/work-orders/utils/day-pagination.test.ts +++ b/src/test/domain/work-orders/utils/day-pagination.test.ts @@ -81,6 +81,28 @@ describe("day pagination utils (SH-241)", () => { expect(shouldShowSearchPagination({ isLoading: false, hasResults: false })).toBe(false); }); + it("shows search pagination when the current page is empty but totalCount is positive", () => { + const pager = pickBoardPager({ + advActive: true, + isLoading: false, + noSearchResults: false, + advResultCount: 0, + search: { page: 99, pageSize: 50, totalCount: 1778 }, + day: { + pageSize: 50, + pageIndex: 0, + pageCount: 1, + itemCount: 0, + footerLabel: "Mon · 08/17", + }, + }); + expect(pager.show).toBe(true); + expect(pager.itemCount).toBe(1778); + expect(pager.pageCount).toBe(36); + expect(pager.pageIndex).toBe(35); + expect(pager.footerLabel).toBe("Results"); + }); + it("pages a 1778-row search at 50 per page without dumping the universe", () => { const pager = pickBoardPager({ advActive: true,