Zayne Rea Sprague
new tab
b630916
import { useEffect, useState } from "react";
import type { OverviewData, PanelNav } from "../types";
interface OverviewLevelProps {
datasetId: string;
fetchOverview: (dsId: string) => Promise<OverviewData>;
onDrillDown: (nav: PanelNav) => void;
}
export default function OverviewLevel({ datasetId, fetchOverview, onDrillDown }: OverviewLevelProps) {
const [data, setData] = useState<OverviewData | null>(null);
useEffect(() => {
fetchOverview(datasetId).then(setData).catch(() => {});
}, [datasetId, fetchOverview]);
if (!data) return <div className="p-4 text-gray-400">Loading overview...</div>;
const correctCount = data.examples.filter((ex) => ex.eval_correct === true).length;
const incorrectCount = data.examples.filter((ex) => ex.eval_correct === false).length;
const unknownCount = data.examples.filter((ex) => ex.eval_correct === null || ex.eval_correct === undefined).length;
return (
<div className="p-4 space-y-3">
{/* Experiment metadata */}
<div className="flex gap-3 text-xs text-gray-400">
<span>Model: <span className="text-gray-200">{data.metadata.model}</span></span>
<span>Method: <span className="text-gray-200">{data.metadata.method}</span></span>
<span>Run: <span className="text-gray-200">{data.metadata.run_id}</span></span>
</div>
{/* Summary stats */}
<div className="flex gap-3 text-xs text-gray-400">
<span>{data.examples.length} examples</span>
{correctCount > 0 && (
<span className="text-emerald-400">{correctCount} correct</span>
)}
{incorrectCount > 0 && (
<span className="text-red-400">{incorrectCount} incorrect</span>
)}
{unknownCount > 0 && (
<span className="text-gray-500">{unknownCount} unknown</span>
)}
</div>
{/* Example cards */}
<div className="space-y-2">
{data.examples.map((ex) => (
<div
key={ex.example_idx}
className="bg-gray-800 border border-gray-700 rounded-lg p-4 hover:border-emerald-500 cursor-pointer transition-colors"
onClick={() =>
onDrillDown({
datasetId,
level: 2,
exampleIdx: ex.example_idx,
})
}
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
<span className="bg-emerald-600 text-white text-xs font-bold px-2 py-0.5 rounded-full">
Ex {ex.example_idx}
</span>
<span className="bg-gray-700 text-gray-300 text-xs px-2 py-0.5 rounded">
{ex.n_iterations} iter{ex.n_iterations !== 1 ? "s" : ""}
</span>
{ex.eval_correct === true && (
<span className="text-emerald-400 text-sm font-bold" title="Correct">
&#10003;
</span>
)}
{ex.eval_correct === false && (
<span className="text-red-400 text-sm font-bold" title="Incorrect">
&#10007;
</span>
)}
</div>
<span className="text-xs text-gray-400">
{ex.total_execution_time.toFixed(1)}s
</span>
</div>
{/* Question preview */}
<div className="text-sm text-gray-300 line-clamp-2 mb-2 leading-relaxed">
{ex.question_text || "(no question text)"}
</div>
<div className="flex gap-4 text-xs text-gray-400">
<span>
{((ex.total_input_tokens + ex.total_output_tokens) / 1000).toFixed(1)}k tokens
</span>
</div>
{ex.final_answer_preview && (
<div className="mt-2 text-xs text-gray-500 truncate">
Answer: {ex.final_answer_preview}
</div>
)}
</div>
))}
</div>
</div>
);
}