From 70501693c877f47b5d0dbe4df08335e8daeb15fd Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Fri, 25 Sep 2026 13:43:11 -0300 Subject: [PATCH] fix(uplifts): show an unavailable count pill while a queue is loading or failed --- src/app/(protected)/uplifts/index.tsx | 35 ++++++++++++++----- .../uplift-approvals-rejected-tab.test.tsx | 27 +++++++++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/app/(protected)/uplifts/index.tsx b/src/app/(protected)/uplifts/index.tsx index aa006cd6..dfa64f3b 100644 --- a/src/app/(protected)/uplifts/index.tsx +++ b/src/app/(protected)/uplifts/index.tsx @@ -18,6 +18,7 @@ import { useAuthContext } from "@/providers/auth-context"; import { useUpliftApprovalController } from "@/domain/uplifts/use-cases/use-uplift-approval-controller"; import { useUpliftsQueue } from "@/domain/uplifts/use-cases/use-uplifts-queue"; import { Text } from "@/components/ui/text"; +import type { UpliftsQueueResult } from "@/domain/uplifts/types/uplift"; const PAGE_SIZE = 25; @@ -47,13 +48,33 @@ const TAB_LABELS: Record = { rejected: "Rejected", }; +// A tab's total is only known once its queue has loaded without error; until then the +// pill must not claim a count (a loading or failed queue is not an empty one). +function knownTotal(query: { + data?: UpliftsQueueResult | undefined; + error: unknown; +}): number | null { + if (query.error || !query.data) return null; + return query.data.totalCount; +} + +function TabCountPill({ tab, count }: { tab: UpliftApprovalTab; count: number | null }) { + return ( + + ); +} + function UpliftApprovalsTabs({ tab, counts, onChange, }: { tab: UpliftApprovalTab; - counts: Record; + counts: Record; onChange: (_event: unknown, value: string) => void; }) { return ( @@ -65,11 +86,7 @@ function UpliftApprovalsTabs({ label={ {TAB_LABELS[value]} - + } /> @@ -152,9 +169,9 @@ export default function UpliftQueuePage() { const activeQuery = queries[tab]; const rows = activeQuery.data?.items ?? []; const counts = { - pending: pendingQuery.data?.totalCount ?? 0, - approved: approvedQuery.data?.totalCount ?? 0, - rejected: rejectedQuery.data?.totalCount ?? 0, + pending: knownTotal(pendingQuery), + approved: knownTotal(approvedQuery), + rejected: knownTotal(rejectedQuery), }; const pendingExposureTotal = pendingQuery.data?.pendingExposureTotal ?? null; diff --git a/src/test/app/(protected)/uplifts/uplift-approvals-rejected-tab.test.tsx b/src/test/app/(protected)/uplifts/uplift-approvals-rejected-tab.test.tsx index 6d7a4134..cfc29305 100644 --- a/src/test/app/(protected)/uplifts/uplift-approvals-rejected-tab.test.tsx +++ b/src/test/app/(protected)/uplifts/uplift-approvals-rejected-tab.test.tsx @@ -9,7 +9,8 @@ import { formatDateTime } from "@/lib/time-utils"; import { renderWithProviders } from "@/test/test-utils"; const queueState = vi.hoisted(() => ({ - byStatus: {} as Record, + byStatus: {} as Record, + errorByStatus: {} as Record, requestedStatuses: [] as Array, })); @@ -92,11 +93,13 @@ function page(items: UpliftQueueItem[], totalCount = items.length): UpliftsQueue vi.mock("@/domain/uplifts/use-cases/use-uplifts-queue", () => ({ useUpliftsQueue: (params: UpliftsQueueParams) => { queueState.requestedStatuses.push(params.status); + const data = queueState.byStatus[params.status ?? ""]; + const error = queueState.errorByStatus[params.status ?? ""] ?? null; return { - data: queueState.byStatus[params.status ?? ""] ?? null, - isLoading: false, + data, + isLoading: data === undefined && error === null, isFetching: false, - error: null, + error, refetch: vi.fn(), }; }, @@ -127,6 +130,7 @@ async function openRejectedTab() { describe("Uplift Approvals rejected tab", () => { beforeEach(() => { queueState.requestedStatuses = []; + queueState.errorByStatus = {}; queueState.byStatus = { Pending: page([pendingItem]), Approved: page([approvedItem]), @@ -145,6 +149,21 @@ describe("Uplift Approvals rejected tab", () => { expect(queueState.requestedStatuses).toContain("Rejected"); }); + it("never claims a count for a queue that is still loading or failed to load", async () => { + queueState.byStatus.Rejected = undefined; + queueState.errorByStatus.Rejected = new Error("Forbidden"); + queueState.byStatus.Approved = undefined; + const { default: UpliftQueuePage } = await import("@/app/(protected)/uplifts/index"); + renderWithProviders(); + + const rejectedPill = screen.getByLabelText("rejected uplift count unavailable"); + expect(rejectedPill).toHaveTextContent("—"); + expect(screen.getByLabelText("approved uplift count unavailable")).toHaveTextContent("—"); + expect(screen.queryByLabelText("0 rejected uplifts")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("0 approved uplifts")).not.toBeInTheDocument(); + expect(screen.getByLabelText("1 pending uplifts")).toBeInTheDocument(); + }); + it("lists only rejected uplifts, in the server's most-recently-rejected order", async () => { const table = await openRejectedTab();