← back to Omega Watches 2
src/components/charts/SourceHealthMap.tsx
80 lines
'use client';
interface SourceHealth {
name: string;
display_name: string;
source_type: string;
success_rate: number;
total_runs: number;
last_run?: string;
is_active: boolean;
}
interface SourceHealthMapProps {
sources: SourceHealth[];
}
function getHealthColor(rate: number): string {
if (rate >= 95) return 'bg-green-500';
if (rate >= 80) return 'bg-yellow-500';
if (rate >= 50) return 'bg-orange-500';
return 'bg-red-500';
}
function getHealthBorder(rate: number): string {
if (rate >= 95) return 'border-green-500/30';
if (rate >= 80) return 'border-yellow-500/30';
if (rate >= 50) return 'border-orange-500/30';
return 'border-red-500/30';
}
export default function SourceHealthMap({ sources }: SourceHealthMapProps) {
if (!sources?.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 data available</p>
</div>
);
}
const grouped = {
auction: sources.filter((s) => s.source_type === 'auction'),
marketplace: sources.filter((s) => s.source_type === 'marketplace'),
dealer: sources.filter((s) => s.source_type === 'dealer'),
forum: sources.filter((s) => s.source_type === 'forum'),
official: sources.filter((s) => s.source_type === 'official'),
};
return (
<div className="bg-navy-800/50 rounded-xl border border-navy-700 p-4">
<h3 className="text-lg font-semibold text-white mb-4">Source Health Map</h3>
<div className="space-y-4">
{Object.entries(grouped).map(([type, srcs]) =>
srcs.length > 0 ? (
<div key={type}>
<p className="text-xs uppercase tracking-wider text-navy-400 mb-2">{type}</p>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2">
{srcs.map((s) => (
<div
key={s.name}
className={`rounded-lg border ${getHealthBorder(s.success_rate)} bg-navy-900/50 p-3 hover:bg-navy-800 transition-colors`}
>
<div className="flex items-center gap-2 mb-1">
<div className={`w-2.5 h-2.5 rounded-full ${getHealthColor(s.success_rate)} ${s.is_active ? 'animate-pulse' : 'opacity-40'}`} />
<span className="text-sm font-medium text-white truncate">{s.display_name}</span>
</div>
<div className="flex items-center justify-between text-xs text-navy-400">
<span>{s.success_rate.toFixed(0)}% success</span>
<span>{s.total_runs} runs</span>
</div>
</div>
))}
</div>
</div>
) : null
)}
</div>
</div>
);
}