← 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>
);
}