From c64c7a7bdff2bea3bebc6ff7cf420663e7e48b91 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 20 Apr 2026 12:56:46 +0000 Subject: [PATCH] added pending removal ui --- .../your-projects/live/LiveTracker.tsx | 26 ++++++++++- .../your-projects/live/PropertyTable.tsx | 46 ++++++++++++++++--- .../live/PropertyTableColumns.tsx | 42 ++++++++++------- .../(portfolio)/your-projects/live/page.tsx | 34 +++++++++++++- .../(portfolio)/your-projects/live/types.ts | 4 ++ 5 files changed, 126 insertions(+), 26 deletions(-) diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/LiveTracker.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/LiveTracker.tsx index 7311c30..8dd230f 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/LiveTracker.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/LiveTracker.tsx @@ -9,7 +9,7 @@ import { TabsTrigger, } from "@/app/shadcn_components/ui/tabs"; import { Card, CardContent } from "@/app/shadcn_components/ui/card"; -import { BarChart2, Table2, FolderOpen, Wrench } from "lucide-react"; +import { BarChart2, Table2, FolderOpen, Wrench, AlertTriangle } from "lucide-react"; import DrillDownTable from "./DrillDownTable"; import PropertyTable from "./PropertyTable"; import DocumentTable from "./DocumentTable"; @@ -24,6 +24,7 @@ import type { ClassifiedDeal, DocumentDrawerState, DocStatusMap, + RemovalStatusByDeal, } from "./types"; export default function LiveTracker({ @@ -33,6 +34,7 @@ export default function LiveTracker({ docStatusMap, userCapability, approvalsByDeal, + removalStatusByDeal, portfolioId, userRole, userEmail, @@ -49,6 +51,12 @@ export default function LiveTracker({ (p) => p.projectCode === currentProjectCode, ); + // ── Pending removal count for current project ──────────────────────── + const pendingRemovalCount = (currentProject?.allDeals ?? []).filter((d) => { + const state = d.dealId ? removalStatusByDeal[d.dealId] : undefined; + return state === "pending_removal" || state === "pending_re_addition"; + }).length; + // ── Drill-down table modal (used by AnalyticsView) ─────────────────── const [openTable, setOpenTable] = useState(null); @@ -117,6 +125,14 @@ export default function LiveTracker({ > Properties + 0 ? "opacity-100" : "opacity-0 pointer-events-none" + }`} + aria-hidden={pendingRemovalCount === 0} + > + {pendingRemovalCount || ""} + )} +
+ + + {pendingRemovalCount}{" "} + {pendingRemovalCount === 1 ? "property has" : "properties have"} an outstanding removal request + +
diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx index db9c867..595106f 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyTable.tsx @@ -38,7 +38,7 @@ import { import { Search, SlidersHorizontal, ChevronLeft, ChevronRight, Download } from "lucide-react"; import { createPropertyTableColumns } from "./PropertyTableColumns"; import { STAGE_ORDER } from "./types"; -import type { ClassifiedDeal, DocStatusMap } from "./types"; +import type { ClassifiedDeal, DocStatusMap, RemovalStatusByDeal, EffectiveRemovalState } from "./types"; // Human-readable labels for toggle dropdown const COLUMN_LABELS: Record = { @@ -58,6 +58,7 @@ const COLUMN_LABELS: Record = { }; type DocFilter = "all" | "has_docs" | "incomplete" | "none"; +type RemovalFilter = "all" | "pending_removal" | "removed" | "pending_re_addition"; interface PropertyTableProps { data: ClassifiedDeal[]; @@ -65,6 +66,7 @@ interface PropertyTableProps { onOpenDetail?: (deal: ClassifiedDeal) => void; showDocuments?: boolean; docStatusMap?: DocStatusMap; + removalStatusByDeal?: RemovalStatusByDeal; } const CSV_FIELDS: { key: keyof ClassifiedDeal; label: string }[] = [ @@ -96,10 +98,11 @@ function escapeCell(value: unknown): string { : str; } -export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDocuments = false, docStatusMap = {} }: PropertyTableProps) { +export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDocuments = false, docStatusMap = {}, removalStatusByDeal = {} }: PropertyTableProps) { const [globalFilter, setGlobalFilter] = useState(""); const [stageFilter, setStageFilter] = useState("all"); const [docFilter, setDocFilter] = useState("all"); + const [removalFilter, setRemovalFilter] = useState("all"); const [sorting, setSorting] = useState([]); const [pagination, setPagination] = useState({ pageIndex: 0, @@ -117,7 +120,7 @@ export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDo fullLodgementDate: false, }); - // Pre-filter by stage and doc status before TanStack gets it + // Pre-filter by stage, doc status, and removal status before TanStack gets it const filteredData = useMemo(() => { let result = data; if (stageFilter !== "all") { @@ -132,12 +135,18 @@ export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDo return true; }); } + if (removalFilter !== "all") { + result = result.filter((d) => { + const state: EffectiveRemovalState = (d.dealId ? removalStatusByDeal[d.dealId] : undefined) ?? "none"; + return state === removalFilter; + }); + } return result; - }, [data, stageFilter, docFilter, docStatusMap]); + }, [data, stageFilter, docFilter, docStatusMap, removalFilter, removalStatusByDeal]); const columns = useMemo( - () => createPropertyTableColumns(onOpenDrawer, showDocuments, docStatusMap, onOpenDetail), - [onOpenDrawer, showDocuments, docStatusMap, onOpenDetail] + () => createPropertyTableColumns(onOpenDrawer, showDocuments, docStatusMap, onOpenDetail, removalStatusByDeal), + [onOpenDrawer, showDocuments, docStatusMap, onOpenDetail, removalStatusByDeal] ); const table = useReactTable({ @@ -227,6 +236,31 @@ export default function PropertyTable({ data, onOpenDrawer, onOpenDetail, showDo + {/* Removal status filter */} + + {/* Docs filter */} {showDocuments && (