mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 18:12:05 +00:00
fix(uplifts): keep a failed queue from rendering as an empty archive
This commit is contained in:
parent
70501693c8
commit
3ed45547db
3 changed files with 51 additions and 11 deletions
|
|
@ -295,9 +295,31 @@ function UpliftApprovalsEmptyState({ tab }: { tab: UpliftApprovalTab }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A failed queue is not an empty one: the page's error alert explains it, so the
|
||||||
|
// empty-state copy must not also claim the list has nothing in it.
|
||||||
|
function UpliftApprovalsEmptyRow({
|
||||||
|
tab,
|
||||||
|
colSpan,
|
||||||
|
hasError,
|
||||||
|
}: {
|
||||||
|
tab: UpliftApprovalTab;
|
||||||
|
colSpan: number;
|
||||||
|
hasError: boolean;
|
||||||
|
}) {
|
||||||
|
if (hasError) return null;
|
||||||
|
return (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={colSpan} align="center" className="py-10">
|
||||||
|
<UpliftApprovalsEmptyState tab={tab} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function UpliftApprovalsTable({
|
export function UpliftApprovalsTable({
|
||||||
tab,
|
tab,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
hasError,
|
||||||
rows,
|
rows,
|
||||||
canRevoke,
|
canRevoke,
|
||||||
onOpenDetail,
|
onOpenDetail,
|
||||||
|
|
@ -309,6 +331,7 @@ export function UpliftApprovalsTable({
|
||||||
}: {
|
}: {
|
||||||
tab: UpliftApprovalTab;
|
tab: UpliftApprovalTab;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
hasError: boolean;
|
||||||
rows: UpliftQueueItem[];
|
rows: UpliftQueueItem[];
|
||||||
canRevoke: boolean;
|
canRevoke: boolean;
|
||||||
onOpenDetail: (row: UpliftQueueItem) => void;
|
onOpenDetail: (row: UpliftQueueItem) => void;
|
||||||
|
|
@ -339,11 +362,7 @@ export function UpliftApprovalsTable({
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : rows.length === 0 ? (
|
) : rows.length === 0 ? (
|
||||||
<TableRow>
|
<UpliftApprovalsEmptyRow tab={tab} colSpan={headerCells.length} hasError={hasError} />
|
||||||
<TableCell colSpan={headerCells.length} align="center" className="py-10">
|
|
||||||
<UpliftApprovalsEmptyState tab={tab} />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
) : (
|
) : (
|
||||||
rows.map((row) => (
|
rows.map((row) => (
|
||||||
<UpliftApprovalRow
|
<UpliftApprovalRow
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ export default function UpliftQueuePage() {
|
||||||
approved: knownTotal(approvedQuery),
|
approved: knownTotal(approvedQuery),
|
||||||
rejected: knownTotal(rejectedQuery),
|
rejected: knownTotal(rejectedQuery),
|
||||||
};
|
};
|
||||||
|
const activeTotal = counts[tab];
|
||||||
const pendingExposureTotal = pendingQuery.data?.pendingExposureTotal ?? null;
|
const pendingExposureTotal = pendingQuery.data?.pendingExposureTotal ?? null;
|
||||||
|
|
||||||
const handleTabChange = (_event: unknown, value: string) => {
|
const handleTabChange = (_event: unknown, value: string) => {
|
||||||
|
|
@ -189,6 +190,7 @@ export default function UpliftQueuePage() {
|
||||||
<UpliftApprovalsTable
|
<UpliftApprovalsTable
|
||||||
tab={tab}
|
tab={tab}
|
||||||
isLoading={activeQuery.isLoading}
|
isLoading={activeQuery.isLoading}
|
||||||
|
hasError={Boolean(activeQuery.error)}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
canRevoke={canRevokeUplifts}
|
canRevoke={canRevokeUplifts}
|
||||||
onOpenDetail={openDetail}
|
onOpenDetail={openDetail}
|
||||||
|
|
@ -198,11 +200,13 @@ export default function UpliftQueuePage() {
|
||||||
onOpenAttachment={openUpliftEvidence}
|
onOpenAttachment={openUpliftEvidence}
|
||||||
isDecisionPending={approvePending || rejectPending || revokePending}
|
isDecisionPending={approvePending || rejectPending || revokePending}
|
||||||
/>
|
/>
|
||||||
<UpliftApprovalsPagination
|
{activeTotal != null && (
|
||||||
count={activeQuery.data?.totalCount ?? 0}
|
<UpliftApprovalsPagination
|
||||||
page={pages[tab]}
|
count={activeTotal}
|
||||||
onPageChange={(page) => setPages((current) => ({ ...current, [tab]: page }))}
|
page={pages[tab]}
|
||||||
/>
|
onPageChange={(page) => setPages((current) => ({ ...current, [tab]: page }))}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{detailItem != null && (
|
{detailItem != null && (
|
||||||
<UpliftDetailModal
|
<UpliftDetailModal
|
||||||
item={detailItem}
|
item={detailItem}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { fireEvent, screen, within } from "@testing-library/react";
|
import { fireEvent, screen, within } from "@testing-library/react";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import type {
|
import type {
|
||||||
UpliftQueueItem,
|
UpliftQueueItem,
|
||||||
UpliftsQueueParams,
|
UpliftsQueueParams,
|
||||||
|
|
@ -128,6 +128,12 @@ async function openRejectedTab() {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("Uplift Approvals rejected tab", () => {
|
describe("Uplift Approvals rejected tab", () => {
|
||||||
|
// Load the page module once up front so the first test's budget is not spent on a
|
||||||
|
// cold import of the whole route.
|
||||||
|
beforeAll(async () => {
|
||||||
|
await import("@/app/(protected)/uplifts/index");
|
||||||
|
}, 60_000);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
queueState.requestedStatuses = [];
|
queueState.requestedStatuses = [];
|
||||||
queueState.errorByStatus = {};
|
queueState.errorByStatus = {};
|
||||||
|
|
@ -164,6 +170,17 @@ describe("Uplift Approvals rejected tab", () => {
|
||||||
expect(screen.getByLabelText("1 pending uplifts")).toBeInTheDocument();
|
expect(screen.getByLabelText("1 pending uplifts")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows the load error instead of an empty archive when the rejected queue fails", async () => {
|
||||||
|
queueState.byStatus.Rejected = undefined;
|
||||||
|
queueState.errorByStatus.Rejected = new Error("Failed to load uplift queue");
|
||||||
|
const table = await openRejectedTab();
|
||||||
|
|
||||||
|
expect(screen.getByRole("alert")).toHaveTextContent("Failed to load uplift queue");
|
||||||
|
expect(within(table).queryByText("No rejected uplifts.")).not.toBeInTheDocument();
|
||||||
|
expect(within(table).queryByTestId("HighlightOffOutlinedIcon")).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(/of 0/)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it("lists only rejected uplifts, in the server's most-recently-rejected order", async () => {
|
it("lists only rejected uplifts, in the server's most-recently-rejected order", async () => {
|
||||||
const table = await openRejectedTab();
|
const table = await openRejectedTab();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue