"use client"; import { useState } from 'react'; const TAG_STYLES = { named: { color: '#10b981', bg: '#10b98120', label: 'Named' }, descriptive: { color: '#f59e0b', bg: '#f59e0b20', label: 'Descriptive' }, vague: { color: '#a78bfa', bg: '#a78bfa20', label: 'Vague' }, 'non-dataset': { color: '#64748b', bg: '#64748b20', label: 'Non-Dataset' }, }; const TAG_OPTIONS = ['named', 'descriptive', 'vague', 'non-dataset']; export default function AnnotationPanel({ isOpen, onClose, datasets, // ALL datasets on current page (model + human) annotatorName, // current user's name onValidate, // (datasetIdx, updates) => void onDelete, }) { const [validatingIdx, setValidatingIdx] = useState(null); const [validationNotes, setValidationNotes] = useState(''); const [editingTagIdx, setEditingTagIdx] = useState(null); const [editTag, setEditTag] = useState(''); const [confirmDelete, setConfirmDelete] = useState(null); const startValidation = (idx, prefillNotes = '') => { setValidatingIdx(idx); setValidationNotes(prefillNotes); }; const submitValidation = (ds, idx, verdict) => { onValidate(ds._rawIndex ?? idx, { human_validated: true, human_verdict: verdict, human_notes: validationNotes.trim() || null, annotator: annotatorName || 'user', validated_at: new Date().toISOString(), }); setValidatingIdx(null); setValidationNotes(''); }; const startEditTag = (idx, currentTag) => { setEditingTagIdx(idx); setEditTag(currentTag); }; const saveEditTag = (ds, idx) => { onValidate(ds._rawIndex ?? idx, { dataset_tag: editTag }); setEditingTagIdx(null); setEditTag(''); }; const handleDelete = (ds, idx) => { if (confirmDelete === idx) { onDelete(ds, idx); setConfirmDelete(null); } else { setConfirmDelete(idx); setTimeout(() => setConfirmDelete(prev => prev === idx ? null : prev), 3000); } }; return ( <> {isOpen &&
}

Data Mentions

{datasets.length}
{datasets.length === 0 ? (

No datasets detected on this page.

) : ( datasets.map((ds, i) => { const text = ds.dataset_name?.text || ''; const tag = ds.dataset_tag || 'named'; const style = TAG_STYLES[tag] || TAG_STYLES.named; const isHuman = !!ds.annotator; // Per-annotator validation: look up current user's entry const myValidation = (ds.validations || []).find(v => v.annotator === annotatorName); const isValidated = myValidation?.human_validated === true; const humanVerdict = myValidation?.human_verdict; const humanNotes = myValidation?.human_notes; const judgeVerdict = ds.dataset_name?.judge_verdict; const judgeTag = ds.dataset_name?.judge_tag; const isValidating = validatingIdx === i; const isEditingTag = editingTagIdx === i; return (
{/* Top row: tag + source */}
{isEditingTag ? (
) : ( startEditTag(i, tag)} title="Click to change tag" > {style.label} )} {isHuman ? `👤 ${ds.annotator}` : '🤖 model'}
{/* Dataset text */}

"{text}"

{/* Judge info (for model extractions) */} {judgeTag && (
Judge: {judgeVerdict ? '✓' : '✕'} {judgeTag}
)} {/* Position info */} {ds.dataset_name?.start != null && ( chars {ds.dataset_name.start}–{ds.dataset_name.end} )} {/* Existing validation status (your own) */} {isValidated && (
{humanVerdict ? '✅ Validated correct' : '❌ Marked incorrect'} by you {humanNotes && (

Note: {humanNotes}

)}
)} {/* Validation UI */} {isValidating ? (