"use client"; import Link from "next/link"; import { Bar, BarChart, CartesianGrid, Cell, Legend, LabelList, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; import { BarChart3, type LucideIcon, Radar } from "lucide-react"; import { SeverityBadge } from "@/components/ui/badge"; import { formatRelative } from "@/lib/format"; import { CHANGE_TYPE_LABELS, SEVERITY_LABELS, SEVERITY_LEVELS, type DashboardAnalytics, type SeverityLevel, } from "@/lib/types"; // Same hex values as tailwind.config.ts's `severity` ramp - a reserved // status scale (good -> critical), never reused as generic categorical // series color. Kept in sync manually since chart libraries need literal // values, not Tailwind classes. const SEVERITY_COLORS: Record = { critical: "#dc2626", high: "#ea580c", medium: "#ca8a04", low: "#65a30d", }; const RUN_STATUS_COLORS = { successful: "#16a34a", failed: "#dc2626", other: "#94a3b8", }; const AXIS_TICK_STYLE = { fill: "#64748b", fontSize: 12 }; const GRID_STROKE = "#e2e8f0"; function ChartCard({ title, icon: Icon, children, }: { title: string; icon: LucideIcon; children: React.ReactNode; }) { return (
{title}
{children}
); } function EmptyChartState({ message }: { message: string }) { return (
{message}
); } function ChangesByTypeChart({ data }: { data: DashboardAnalytics["changes_by_type"] }) { const rows = Object.entries(data) .map(([key, value]) => ({ key, label: CHANGE_TYPE_LABELS[key] ?? key, value })) .filter((r) => r.value > 0) .sort((a, b) => b.value - a.value); if (rows.length === 0) { return ; } return ( [value, "Changes"]} /> ); } function AlertsBySeverityChart({ data }: { data: DashboardAnalytics["alerts_by_severity"] }) { const total = SEVERITY_LEVELS.reduce((sum, s) => sum + (data[s] ?? 0), 0); if (total === 0) { return ; } const rows = SEVERITY_LEVELS.map((severity) => ({ severity, label: SEVERITY_LABELS[severity], value: data[severity] ?? 0, })); return ( [value, "Alerts"]} /> {rows.map((row) => ( ))} ); } function RunsByDayChart({ data }: { data: DashboardAnalytics["runs_by_day"] }) { if (data.length === 0) { return ; } const rows = data.map((d) => ({ ...d, label: new Date(d.date).toLocaleDateString(undefined, { month: "short", day: "numeric" }), })); return ( ); } function RecentSignalsFeed({ signals }: { signals: DashboardAnalytics["recent_signals"] }) { if (signals.length === 0) { return (

No signals detected yet — once a monitoring run finds a real change, it'll show up here.

); } return (
    {signals.map((signal) => (
  • {CHANGE_TYPE_LABELS[signal.change_type] ?? signal.change_type}

    {signal.summary}

    {signal.company_name}
    {formatRelative(signal.created_at)}
  • ))}
); } export function DashboardAnalyticsSection({ analytics }: { analytics: DashboardAnalytics }) { return (
Recent intelligence signals
); }