From 1ff532aa3aea8b50582b15b2e6878d570a8b6bf2 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 1 Apr 2026 17:29:32 +0000 Subject: [PATCH] added missing survey issues --- .../your-projects/live/SurveyIssuesPanel.tsx | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx new file mode 100644 index 0000000..37ba210 --- /dev/null +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx @@ -0,0 +1,107 @@ +"use client"; + +import { motion } from "framer-motion"; +import { AlertCircle } from "lucide-react"; +import { Card, CardContent } from "@/app/shadcn_components/ui/card"; +import type { ClassifiedDeal } from "./types"; + +const SUCCESSFUL_OUTCOMES = new Set(["Surveyed", "Surveyed - Pending Upload"]); + +const COLUMNS: (keyof ClassifiedDeal)[] = [ + "dealname", + "landlordPropertyId", + "outcome", + "outcomeNotes", +]; +const COLUMN_LABELS: Partial> = { + dealname: "Address", + landlordPropertyId: "Ref", + outcome: "Outcome", + outcomeNotes: "Notes", +}; + +interface SurveyIssuesPanelProps { + deals: ClassifiedDeal[]; + onOpenTable: ( + stage: string, + deals: ClassifiedDeal[], + columns?: (keyof ClassifiedDeal)[], + columnLabels?: Partial>, + breakdown?: Record, + ) => void; +} + +export default function SurveyIssuesPanel({ + deals, + onOpenTable, +}: SurveyIssuesPanelProps) { + // Filter to deals with a populated outcome that is not a success + const issueDeals = deals.filter( + (d) => d.outcome && !SUCCESSFUL_OUTCOMES.has(d.outcome), + ); + + if (issueDeals.length === 0) return null; + + // Group by outcome, sorted by count descending + const groups = new Map(); + for (const deal of issueDeals) { + const key = deal.outcome!; + if (!groups.has(key)) groups.set(key, []); + groups.get(key)!.push(deal); + } + const sortedGroups = [...groups.entries()].sort( + (a, b) => b[1].length - a[1].length, + ); + + return ( + + +
+
+
+ +

+ Survey Issues +

+ + {issueDeals.length} affected + +
+

+ Properties where the survey did not result in a successful outcome +

+
+
+ +
+ {sortedGroups.map(([outcomeLabel, groupDeals]) => ( + + onOpenTable( + `Survey Issues — ${outcomeLabel}`, + groupDeals, + COLUMNS, + COLUMN_LABELS, + ) + } + className="group text-left rounded-xl border border-amber-200 bg-gradient-to-br from-amber-50 to-white p-4 hover:border-amber-300 hover:shadow-md transition-all duration-200" + > +

+ {outcomeLabel} +

+

+ {groupDeals.length} +

+

+ {((groupDeals.length / issueDeals.length) * 100).toFixed(0)}% of + issues +

+
+ ))} +
+
+
+ ); +}