mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 04:33:11 +00:00
fix(uplifts): show an unavailable count pill while a queue is loading or failed
This commit is contained in:
parent
70e52937aa
commit
70501693c8
2 changed files with 49 additions and 13 deletions
|
|
@ -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<UpliftApprovalTab, string> = {
|
|||
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 (
|
||||
<Chip
|
||||
size="small"
|
||||
label={count ?? "—"}
|
||||
aria-label={count == null ? `${tab} uplift count unavailable` : `${count} ${tab} uplifts`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function UpliftApprovalsTabs({
|
||||
tab,
|
||||
counts,
|
||||
onChange,
|
||||
}: {
|
||||
tab: UpliftApprovalTab;
|
||||
counts: Record<UpliftApprovalTab, number>;
|
||||
counts: Record<UpliftApprovalTab, number | null>;
|
||||
onChange: (_event: unknown, value: string) => void;
|
||||
}) {
|
||||
return (
|
||||
|
|
@ -65,11 +86,7 @@ function UpliftApprovalsTabs({
|
|||
label={
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: "center" }}>
|
||||
<span>{TAB_LABELS[value]}</span>
|
||||
<Chip
|
||||
size="small"
|
||||
label={counts[value]}
|
||||
aria-label={`${counts[value]} ${value} uplifts`}
|
||||
/>
|
||||
<TabCountPill tab={value} count={counts[value]} />
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import { formatDateTime } from "@/lib/time-utils";
|
|||
import { renderWithProviders } from "@/test/test-utils";
|
||||
|
||||
const queueState = vi.hoisted(() => ({
|
||||
byStatus: {} as Record<string, UpliftsQueueResult>,
|
||||
byStatus: {} as Record<string, UpliftsQueueResult | undefined>,
|
||||
errorByStatus: {} as Record<string, Error | undefined>,
|
||||
requestedStatuses: [] as Array<string | undefined>,
|
||||
}));
|
||||
|
||||
|
|
@ -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(<UpliftQueuePage />);
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue