added missing survey issues

This commit is contained in:
Khalim Conn-Kowlessar 2026-04-01 17:29:32 +00:00
parent 4106dc3e2d
commit 1ff532aa3a

View file

@ -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<Record<keyof ClassifiedDeal, string>> = {
dealname: "Address",
landlordPropertyId: "Ref",
outcome: "Outcome",
outcomeNotes: "Notes",
};
interface SurveyIssuesPanelProps {
deals: ClassifiedDeal[];
onOpenTable: (
stage: string,
deals: ClassifiedDeal[],
columns?: (keyof ClassifiedDeal)[],
columnLabels?: Partial<Record<keyof ClassifiedDeal, string>>,
breakdown?: Record<string, ClassifiedDeal[]>,
) => 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<string, ClassifiedDeal[]>();
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 (
<Card className="border border-amber-200 shadow-sm">
<CardContent className="p-6">
<div className="flex items-center justify-between mb-5">
<div>
<div className="flex items-center gap-2">
<AlertCircle className="h-4 w-4 text-amber-500" />
<h3 className="text-base font-semibold text-amber-800">
Survey Issues
</h3>
<span className="ml-2 px-2 py-0.5 rounded-full bg-amber-100 text-amber-700 text-xs font-semibold">
{issueDeals.length} affected
</span>
</div>
<p className="text-sm text-gray-500 mt-0.5">
Properties where the survey did not result in a successful outcome
</p>
</div>
</div>
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
{sortedGroups.map(([outcomeLabel, groupDeals]) => (
<motion.button
key={outcomeLabel}
whileHover={{ scale: 1.03 }}
onClick={() =>
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"
>
<p className="text-xs font-semibold text-amber-700 uppercase tracking-wide mb-2 leading-tight">
{outcomeLabel}
</p>
<p className="text-2xl font-bold text-amber-800">
{groupDeals.length}
</p>
<p className="text-xs text-amber-600/70 mt-0.5">
{((groupDeals.length / issueDeals.length) * 100).toFixed(0)}% of
issues
</p>
</motion.button>
))}
</div>
</CardContent>
</Card>
);
}