diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-body.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-body.tsx
index 65f49dbd..7e51c960 100644
--- a/src/app/(protected)/workorders/_components/list/table/wo-table-body.tsx
+++ b/src/app/(protected)/workorders/_components/list/table/wo-table-body.tsx
@@ -23,8 +23,14 @@ export function WoTableBody({ tableData, renderRow, renderInlineRow }: WoTableBo
const unassignedRows = tableData.unassigned ?? [];
const showUnscheduled =
(tableData.unscheduled?.length ?? 0) > 0 || tableData.draftDayKey === UNSCHEDULED_DAY_KEY;
+ // SH-165: "still loading" and "zero unassigned" are distinct states. Without
+ // this split the pin announced "No unassigned work orders." while the queue
+ // was still paging board/search on first mount.
const showUnassignedLoading =
- tableData.unassignedOpen && Boolean(tableData.unassignedLoading) && !tableData.unassignedError;
+ tableData.unassignedOpen &&
+ unassignedRows.length === 0 &&
+ !tableData.unassignedError &&
+ tableData.unassignedLoading;
const showUnassignedEmpty =
tableData.unassignedOpen &&
unassignedRows.length === 0 &&
@@ -53,10 +59,10 @@ export function WoTableBody({ tableData, renderRow, renderInlineRow }: WoTableBo
)}
{showUnassignedLoading && (
-
+
|
- Loading unassigned work orders.
+ Loading unassigned work orders…
|
diff --git a/src/app/(protected)/workorders/_hooks/use-work-orders-board-source.ts b/src/app/(protected)/workorders/_hooks/use-work-orders-board-source.ts
index 2227e3f9..914bf835 100644
--- a/src/app/(protected)/workorders/_hooks/use-work-orders-board-source.ts
+++ b/src/app/(protected)/workorders/_hooks/use-work-orders-board-source.ts
@@ -76,7 +76,7 @@ export function useWorkOrdersBoardSource(filters: FiltersReturn): WorkOrdersBoar
} = useWorkOrdersBoardSearch(resolvedSearchParams ?? { datePreset: "ThisWeek" }, advActive);
const {
data: queueData,
- isPending: queuePending,
+ isLoading: queueLoading,
isFetching: queueFetching,
error: queueError,
refetch: refetchQueue,
@@ -96,7 +96,10 @@ export function useWorkOrdersBoardSource(filters: FiltersReturn): WorkOrdersBoar
data: advActive ? searchData : boardData,
unassignedQueue: advActive ? EMPTY_UNASSIGNED_QUEUE : (queueData ?? EMPTY_UNASSIGNED_QUEUE),
unassignedError: advActive ? null : (queueError ?? null),
- unassignedLoading: advActive ? false : queuePending,
+ // SH-165: the pinned queue has its own first-load state. Folding it into
+ // isFetching only made "still paging board/search" indistinguishable from
+ // "zero unassigned", so the pin announced an empty queue while loading.
+ unassignedLoading: advActive ? false : queueLoading,
isLoading: advActive ? searchLoading : boardLoading,
isFetching: advActive ? searchFetching : boardFetching || queueFetching,
error: advActive ? searchError : boardError,
diff --git a/src/test/app/(protected)/workorders/wo-table-unassigned-queue.test.tsx b/src/test/app/(protected)/workorders/wo-table-unassigned-queue.test.tsx
index a3461cd9..66a61208 100644
--- a/src/test/app/(protected)/workorders/wo-table-unassigned-queue.test.tsx
+++ b/src/test/app/(protected)/workorders/wo-table-unassigned-queue.test.tsx
@@ -309,6 +309,36 @@ describe("WoTableBody Unassigned queue (SH-165)", () => {
expect(screen.queryByText("WED · 07/15")).not.toBeInTheDocument();
});
+ it("distinguishes a still-loading queue from an empty one", () => {
+ render(
+
+ null}
+ renderInlineRow={() => null}
+ />
+
,
+ );
+
+ expect(screen.getByText(/Loading unassigned work orders/)).toBeInTheDocument();
+ expect(screen.queryByText("No unassigned work orders.")).not.toBeInTheDocument();
+ });
+
+ it("announces an empty queue only once loading has settled", () => {
+ render(
+
+ null}
+ renderInlineRow={() => null}
+ />
+
,
+ );
+
+ expect(screen.getByText("No unassigned work orders.")).toBeInTheDocument();
+ expect(screen.queryByText(/Loading unassigned work orders/)).not.toBeInTheDocument();
+ });
+
it("keeps the Unassigned pin visible when the queue query fails", () => {
render(
@@ -351,25 +381,6 @@ describe("WoTableBody Unassigned queue (SH-165)", () => {
expect(screen.queryByTestId(/row-/)).not.toBeInTheDocument();
});
- it("shows a loading state instead of empty while the unassigned queue is pending", () => {
- render(
-
- (
-
- | {row.woNumber} |
-
- )}
- renderInlineRow={() => null}
- />
-
,
- );
-
- expect(screen.getByText("Loading unassigned work orders.")).toBeInTheDocument();
- expect(screen.queryByText("No unassigned work orders.")).not.toBeInTheDocument();
- });
-
it("removes a pinned row immediately after assigning through the board PATCH path", async () => {
const user = userEvent.setup();
const pinned = makeRow({