import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { FaDownload } from 'react-icons/fa' import { api } from '../../api/client' import { createSSE } from '../../api/sse' import { getClassColor } from './classColors' import type { Media, AnnotationListItem, PaginatedResponse } from '../../types' interface Props { media: Media | null annotations: AnnotationListItem[] selectedAnnotation: AnnotationListItem | null onSelect: (ann: AnnotationListItem) => void onAnnotationsUpdate: (anns: AnnotationListItem[]) => void onDownload?: (ann: AnnotationListItem) => void } export default function AnnotationsSidebar({ media, annotations, selectedAnnotation, onSelect, onAnnotationsUpdate, onDownload }: Props) { const { t } = useTranslation() const [detecting, setDetecting] = useState(false) const [detectLog, setDetectLog] = useState([]) useEffect(() => { if (!media) return return createSSE<{ annotationId: string; mediaId: string; status: number }>('/api/annotations/annotations/events', (event) => { if (event.mediaId === media.id) { api.get>( `/api/annotations/annotations?mediaId=${media.id}&pageSize=1000` ).then(res => onAnnotationsUpdate(res.items)).catch(() => {}) } }) }, [media, onAnnotationsUpdate]) const handleDetect = async () => { if (!media) return setDetecting(true) setDetectLog(['Starting AI detection...']) try { await api.post(`/api/detect/${media.id}`) setDetectLog(prev => [...prev, 'Detection complete.']) } catch (e: any) { setDetectLog(prev => [...prev, `Error: ${e.message}`]) } } const getRowGradient = (ann: AnnotationListItem) => { if (ann.detections.length === 0) return 'rgba(221,221,221,0.25)' const stops = ann.detections.map((d, i) => { const pct = (i / Math.max(ann.detections.length - 1, 1)) * 100 const alpha = Math.min(1, d.confidence) return `${getClassColor(d.classNum)}${Math.round(alpha * 40).toString(16).padStart(2, '0')} ${pct}%` }) return `linear-gradient(to right, ${stops.join(', ')})` } return (
{t('annotations.title')}
{annotations.map(ann => (
onSelect(ann)} className={`px-2 py-1 cursor-pointer border-b border-az-border text-xs ${ selectedAnnotation?.id === ann.id ? 'ring-1 ring-az-orange ring-inset' : '' }`} style={{ background: getRowGradient(ann) }} >
{ann.time || '—'} {ann.detections.length > 0 ? ann.detections[0].label : '—'}
))} {annotations.length === 0 && (
{t('common.noData')}
)}
{detecting && (

{t('annotations.detect')}

{detectLog.map((line, i) =>
{line}
)}
)}
) }