From 5aed31392cfa1315c2e71ca60d0c2275f87d1248 Mon Sep 17 00:00:00 2001 From: Codex Review Integration Date: Wed, 16 Sep 2026 22:44:37 -0300 Subject: [PATCH] fix(uplifts): complete approval queue review fixes (SH-208) --- .../_components/uplift-approvals-table.tsx | 37 +++++++++++++++---- .../_components/uplift-detail-modal.tsx | 29 ++++++++++++--- src/app/(protected)/uplifts/index.tsx | 17 ++------- .../uplift-approvals-approved-tab.test.tsx | 4 ++ 4 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/app/(protected)/uplifts/_components/uplift-approvals-table.tsx b/src/app/(protected)/uplifts/_components/uplift-approvals-table.tsx index 8aa2ec8c..2ab99236 100644 --- a/src/app/(protected)/uplifts/_components/uplift-approvals-table.tsx +++ b/src/app/(protected)/uplifts/_components/uplift-approvals-table.tsx @@ -15,7 +15,7 @@ import { import { formatUpliftMoney } from "@/app/(protected)/uplifts/_components/format-uplift-money"; import { Text } from "@/components/ui/text"; import type { UpliftQueueItem } from "@/domain/uplifts/types/uplift"; -import { getWaitTimeTextClass, timeSince, waitTimeColor } from "@/lib/time-utils"; +import { formatDateTime, getWaitTimeTextClass, timeSince, waitTimeColor } from "@/lib/time-utils"; export type UpliftApprovalTab = "pending" | "approved"; @@ -223,9 +223,16 @@ function UpliftApprovalRow({ {row.requestedByVendorName || "—"} - - - + {tab === "pending" ? ( + + + + ) : ( + <> + {row.decidedByName || "—"} + {row.decidedAt ? formatDateTime(row.decidedAt) : "—"} + + )} {tab === "pending" ? ( void; isDecisionPending: boolean; }) { + const headerCells = tab === "pending" ? PENDING_HEADER_CELLS : APPROVED_HEADER_CELLS; return ( - {HEADER_CELLS.map((label) => ( + {headerCells.map((label) => ( {label} @@ -290,13 +311,13 @@ export function UpliftApprovalsTable({ {isLoading ? ( - + ) : rows.length === 0 ? ( - + {tab === "pending" ? ( No uplifts waiting for approval. diff --git a/src/app/(protected)/uplifts/_components/uplift-detail-modal.tsx b/src/app/(protected)/uplifts/_components/uplift-detail-modal.tsx index 8fb24905..04ac0b56 100644 --- a/src/app/(protected)/uplifts/_components/uplift-detail-modal.tsx +++ b/src/app/(protected)/uplifts/_components/uplift-detail-modal.tsx @@ -25,6 +25,7 @@ type ModalCallbacks = { onApprove: (row: UpliftQueueItem) => void; onReject: (row: UpliftQueueItem) => void; onRevoke: (row: UpliftQueueItem) => void; + onOpenAttachment: (row: UpliftQueueItem) => void; }; function DetailField({ label, children }: { label: string; children: ReactNode }) { @@ -49,7 +50,13 @@ function DetailSection({ title, children }: { title: string; children: ReactNode ); } -function UpliftAttachments({ item }: { item: UpliftQueueItem }) { +function UpliftAttachments({ + item, + onOpenAttachment, +}: { + item: UpliftQueueItem; + onOpenAttachment: (row: UpliftQueueItem) => void; +}) { if (item.evidenceDocumentId == null && !item.evidenceFileName) { return ( @@ -63,7 +70,12 @@ function UpliftAttachments({ item }: { item: UpliftQueueItem }) { : 0; return ( - + onOpenAttachment(item) : undefined} + clickable={item.evidenceDocumentId != null} + /> {extraCount > 0 && } ); @@ -91,7 +103,13 @@ function WorkOrderSection({ item, info }: { item: UpliftQueueItem; info?: WorkOr ); } -function RequestSection({ item }: { item: UpliftQueueItem }) { +function RequestSection({ + item, + onOpenAttachment, +}: { + item: UpliftQueueItem; + onOpenAttachment: (row: UpliftQueueItem) => void; +}) { const waitingClass = item.requestedAt ? getWaitTimeTextClass(waitTimeColor(item.requestedAt)) : undefined; @@ -114,7 +132,7 @@ function RequestSection({ item }: { item: UpliftQueueItem }) { {item.vendorReason || "No justification provided."} - + ); @@ -269,6 +287,7 @@ export function UpliftDetailModal({ onApprove, onReject, onRevoke, + onOpenAttachment, }: { item: UpliftQueueItem | null; approvePending: boolean; @@ -326,7 +345,7 @@ export function UpliftDetailModal({ - + - a.requestedAt < b.requestedAt ? -1 : a.requestedAt > b.requestedAt ? 1 : 0, - ); - } else { - copy.sort((a, b) => (a.decidedAt > b.decidedAt ? -1 : a.decidedAt < b.decidedAt ? 1 : 0)); - } - return copy; -} - function UpliftApprovalsHeader({ pendingExposureTotal }: { pendingExposureTotal: number | null }) { return ( @@ -151,7 +139,7 @@ export default function UpliftQueuePage() { } = useUpliftApprovalController(); const activeQuery = tab === "pending" ? pendingQuery : approvedQuery; - const rows = useMemo(() => sortRows(activeQuery.data?.items ?? [], tab), [activeQuery.data, tab]); + const rows = activeQuery.data?.items ?? []; const pendingCount = pendingQuery.data?.totalCount ?? 0; const pendingExposureTotal = pendingQuery.data?.pendingExposureTotal ?? null; @@ -204,6 +192,7 @@ export default function UpliftQueuePage() { onApprove={handleApprove} onReject={handleRejectRequest} onRevoke={handleRevokeRequest} + onOpenAttachment={handleOpenAttachment} /> )} { renderWithProviders(); fireEvent.click(screen.getByRole("tab", { name: "Approved" })); + expect(screen.getByRole("columnheader", { name: "Approved By" })).toBeInTheDocument(); + expect(screen.getByRole("columnheader", { name: "Approved At" })).toBeInTheDocument(); + expect(screen.queryByRole("columnheader", { name: "Waiting" })).not.toBeInTheDocument(); + expect(screen.getByText("Admin User")).toBeInTheDocument(); const revoke = await screen.findByRole("button", { name: "Revoke" }); expect(revoke).toBeDisabled(); fireEvent.mouseOver(revoke);