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