// components/GroupReport.tsx // Client component for group report table — sortable, exportable. "use client"; import { useState } from "react"; import Link from "next/link"; import type { YsterbaardGroup, YsterbaardCompany } from "@/lib/types"; interface Props { group: YsterbaardGroup; companies: YsterbaardCompany[]; } type SortKey = "enterprise_name" | "enterprise_no" | "sars_tax_number" | "sars_vat_no" | "sars_paye_no" | "enterprise_status"; export default function GroupReport({ group, companies }: Props) { const [sortKey, setSortKey] = useState("enterprise_name"); const [sortDir, setSortDir] = useState<"asc" | "desc">("asc"); const sorted = [...companies].sort((a, b) => { const av = String((a[sortKey] ?? "") || ""); const bv = String((b[sortKey] ?? "") || ""); const cmp = av.localeCompare(bv); return sortDir === "asc" ? cmp : -cmp; }); function toggleSort(k: SortKey) { if (k === sortKey) { setSortDir(d => d === "asc" ? "desc" : "asc"); } else { setSortKey(k); setSortDir("asc"); } } function sortIcon(k: SortKey) { if (k !== sortKey) return "↕"; return sortDir === "asc" ? "↑" : "↓"; } function exportCSV() { const headers = ["Enterprise No", "Company Name", "Income Tax", "VAT", "PAYE", "Status", "Edit", "View"]; const rows = sorted.map(c => [ c.enterprise_no || "", c.enterprise_name || "", c.sars_tax_number || "", c.sars_vat_no || "", c.sars_paye_no || "", c.enterprise_status || "", `/companies/${c.id}`, `/companies/${c.id}`, ]); const csv = [headers, ...rows] .map(r => r.map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(",")) .join("\n"); const blob = new Blob([csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `${group.name}-report-${new Date().toISOString().slice(0, 10)}.csv`; a.click(); URL.revokeObjectURL(url); } const stats = { total: companies.length, withTax: companies.filter(c => c.sars_tax_number).length, withVat: companies.filter(c => c.sars_vat_no).length, withPaye: companies.filter(c => c.sars_paye_no).length, inBusiness: companies.filter(c => (c.enterprise_status || "").toLowerCase().includes("business")).length, }; return (
{/* Stats cards */}
0 ? "green" : "muted"} />
{/* Toolbar */}

Showing {sorted.length} of {companies.length} compan{companies.length === 1 ? "y" : "ies"}

{/* Report table */} {sorted.length === 0 ? (
No companies are currently in the {group.name} group.
) : (
{sorted.map(c => ( ))}
Edit View
{c.enterprise_no || —} {c.enterprise_name || —} {c.sars_tax_number || —} {c.sars_vat_no || —} {c.sars_paye_no || —} {c.enterprise_status || "—"} Edit View →
)}
); } function StatCard({ label, value, highlight = "muted" }: { label: string; value: number; highlight?: "green" | "red" | "muted" }) { const colors = { green: "text-green-700", red: "text-red-600", muted: "text-fg", }; return (

{label}

{value}

); } function SortHeader({ label, sortKey, current, dir, onSort, icon }: { label: string; sortKey: SortKey; current: SortKey; dir: "asc" | "desc"; onSort: (k: SortKey) => void; icon: (k: SortKey) => string; }) { const isActive = current === sortKey; return ( ); }