← back to Omega Watches 2

src/components/charts/SourceHealthDonut.tsx

91 lines

'use client';

import { ResponsiveContainer, PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';

interface SourceData {
  name: string;
  source_type: string;
  success_rate: number;
  total_runs: number;
  records: number;
}

interface SourceHealthDonutProps {
  data: SourceData[];
  title?: string;
}

function getHealthColor(rate: number): string {
  if (rate >= 95) return '#22c55e';
  if (rate >= 80) return '#f59e0b';
  if (rate >= 50) return '#f97316';
  return '#ef4444';
}

const CustomTooltip = ({ active, payload }: any) => {
  if (!active || !payload?.length) return null;
  const d = payload[0].payload;
  return (
    <div className="bg-navy-800 border border-navy-600 rounded-lg p-3 shadow-xl">
      <p className="text-sm font-medium text-white">{d.name}</p>
      <p className="text-xs text-navy-300">Type: {d.source_type}</p>
      <p className="text-xs" style={{ color: getHealthColor(d.success_rate) }}>
        Success: {d.success_rate}%
      </p>
      <p className="text-xs text-navy-300">{d.total_runs} runs · {d.records.toLocaleString()} records</p>
    </div>
  );
};

export default function SourceHealthDonut({ data, title }: SourceHealthDonutProps) {
  if (!data?.length) {
    return (
      <div className="bg-navy-800/50 rounded-xl border border-navy-700 p-8 text-center">
        <p className="text-navy-400">No source health data available</p>
      </div>
    );
  }

  const chartData = data.filter((d) => d.total_runs > 0);
  const totalSources = chartData.length;

  return (
    <div className="bg-navy-800/50 rounded-xl border border-navy-700 p-4">
      {title && <h3 className="text-sm font-semibold uppercase tracking-wider text-gray-400 mb-4">{title}</h3>}
      <div className="relative">
        <ResponsiveContainer width="100%" height={280}>
          <PieChart>
            <Pie
              data={chartData}
              dataKey="total_runs"
              nameKey="name"
              cx="50%"
              cy="50%"
              outerRadius={90}
              innerRadius={55}
              strokeWidth={2}
              stroke="#0f1623"
            >
              {chartData.map((entry, i) => (
                <Cell key={i} fill={getHealthColor(entry.success_rate)} />
              ))}
            </Pie>
            <Tooltip content={<CustomTooltip />} />
            <Legend
              formatter={(value: string) => (
                <span className="text-xs text-navy-300">{value}</span>
              )}
            />
          </PieChart>
        </ResponsiveContainer>
        <div className="absolute inset-0 flex items-center justify-center pointer-events-none" style={{ marginBottom: 40 }}>
          <div className="text-center">
            <div className="text-2xl font-bold text-white">{totalSources}</div>
            <div className="text-[10px] text-gray-500 uppercase">Sources</div>
          </div>
        </div>
      </div>
    </div>
  );
}