import {
Box,
Button,
Chip,
CircularProgress,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Tooltip,
} from "@mui/material";
import {
formatUpliftMoney,
isGrantedAmount,
} from "@/app/(protected)/uplifts/_components/format-uplift-money";
import {
UPLIFT_APPROVAL_HEADER_CELLS,
type UpliftApprovalTab,
} from "@/app/(protected)/uplifts/_components/uplift-approval-tabs";
import {
RejectedEmptyState,
RejectedRowCells,
} from "@/app/(protected)/uplifts/_components/uplift-rejected-cells";
import { Text } from "@/components/ui/text";
import { useUpliftsCanApprove } from "@/domain/uplifts/use-cases/use-uplifts-can-approve";
import { upliftAmount } from "@/domain/uplifts/utils/uplift-amount";
import type { UpliftQueueItem } from "@/domain/uplifts/types/uplift";
import { formatDateTime, getWaitTimeTextClass, timeSince, waitTimeColor } from "@/lib/time-utils";
const CLOSED_WO_TOOLTIP = "This work order is closed. Uplifts can no longer be revoked.";
const ADMIN_ONLY_REVOKE_TOOLTIP = "Only admins can revoke uplifts";
function workOrderLabel(row: UpliftQueueItem): string {
return row.woNumber || row.dispatchNumber || "—";
}
function WaitingCell({ row }: { row: UpliftQueueItem }) {
if (!row.requestedAt) {
return (
—
);
}
const color = waitTimeColor(row.requestedAt);
const className = getWaitTimeTextClass(color);
return (
{timeSince(row.requestedAt)}
);
}
function AttachmentsCell({
row,
onOpenAttachment,
}: {
row: UpliftQueueItem;
onOpenAttachment: (row: UpliftQueueItem) => void;
}) {
if (row.evidenceDocumentId == null && !row.evidenceFileName) {
return (
—
);
}
const extraCount =
typeof row.attachmentCount === "number" && row.attachmentCount > 1
? row.attachmentCount - 1
: 0;
return (
onOpenAttachment(row) : undefined}
clickable={row.evidenceDocumentId != null}
/>
{extraCount > 0 && }
);
}
function PendingRowActions({
row,
onApprove,
onReject,
isDecisionPending,
}: {
row: UpliftQueueItem;
onApprove: (row: UpliftQueueItem) => void;
onReject: (row: UpliftQueueItem) => void;
isDecisionPending: boolean;
}) {
const canApproveTier = useUpliftsCanApprove(row.requiredTier);
const canDecide = row.canDecide && canApproveTier.data === true;
const tooltip = canDecide ? "" : `Requires Tier ${row.requiredTier} role`;
return (
e.stopPropagation()}>
);
}
function ApprovedRowActions({
row,
canRevoke,
onRevoke,
isDecisionPending,
}: {
row: UpliftQueueItem;
canRevoke: boolean;
onRevoke: (row: UpliftQueueItem) => void;
isDecisionPending: boolean;
}) {
const closed = row.workOrderClosed === true;
const tooltip = !canRevoke ? ADMIN_ONLY_REVOKE_TOOLTIP : closed ? CLOSED_WO_TOOLTIP : "";
return (
e.stopPropagation()}>
);
}
function UpliftApprovalRow({
row,
tab,
canRevoke,
onOpenDetail,
onApprove,
onReject,
onRevoke,
onOpenAttachment,
isDecisionPending,
}: {
row: UpliftQueueItem;
tab: UpliftApprovalTab;
canRevoke: boolean;
onOpenDetail: (row: UpliftQueueItem) => void;
onApprove: (row: UpliftQueueItem) => void;
onReject: (row: UpliftQueueItem) => void;
onRevoke: (row: UpliftQueueItem) => void;
onOpenAttachment: (row: UpliftQueueItem) => void;
isDecisionPending: boolean;
}) {
return (
onOpenDetail(row)}
onKeyDown={(e) => {
if (e.key === "Enter") onOpenDetail(row);
}}
tabIndex={0}
aria-label={`Open uplift details for ${workOrderLabel(row)}`}
>
{workOrderLabel(row)}
{Boolean(row.site) && (
{row.site}
)}
{Boolean(row.serviceName) && (
{row.serviceName}
)}
{row.vendorCompanyName || "—"}
{formatUpliftMoney(upliftAmount(row))}
{isGrantedAmount(row.approvedOnWoTotal) ? (
{formatUpliftMoney(row.approvedOnWoTotal)}
) : (
—
)}
{row.vendorReason}
{row.requestedByVendorName || "—"}
{tab === "pending" && (
<>
>
)}
{tab === "approved" && (
<>
{row.decidedByName || "—"}
{row.decidedAt ? formatDateTime(row.decidedAt) : "—"}
>
)}
{tab === "rejected" && }
);
}
function UpliftApprovalsEmptyState({ tab }: { tab: UpliftApprovalTab }) {
if (tab === "rejected") return ;
if (tab === "approved") {
return (
No approved uplifts yet
Uplifts you approve are archived here for reference.
);
}
return (
No uplifts waiting for approval.
);
}
// 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 (
);
}
export function UpliftApprovalsTable({
tab,
isLoading,
hasError,
rows,
canRevoke,
onOpenDetail,
onApprove,
onReject,
onRevoke,
onOpenAttachment,
isDecisionPending,
}: {
tab: UpliftApprovalTab;
isLoading: boolean;
hasError: boolean;
rows: UpliftQueueItem[];
canRevoke: boolean;
onOpenDetail: (row: UpliftQueueItem) => void;
onApprove: (row: UpliftQueueItem) => void;
onReject: (row: UpliftQueueItem) => void;
onRevoke: (row: UpliftQueueItem) => void;
onOpenAttachment: (row: UpliftQueueItem) => void;
isDecisionPending: boolean;
}) {
const headerCells = UPLIFT_APPROVAL_HEADER_CELLS[tab];
return (
{headerCells.map((label) => (
{label}
))}
{isLoading ? (
) : rows.length === 0 ? (
) : (
rows.map((row) => (
))
)}
);
}