import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { api, endpoints } from '../api' // classColors lives under 06_annotations until F3 moves it to its own home. // Importing through the 06_annotations barrel would create a cycle // (DetectionClasses -> 06_annotations barrel -> AnnotationsPage -> DetectionClasses). // STC-ARCH-01 exempts this single path as an F3-pending edge. import { getClassColor, FALLBACK_CLASS_NAMES } from '../class-colors' import type { DetectionClass } from '../types' interface Props { selectedClassNum: number onSelect: (classNum: number) => void photoMode: number onPhotoModeChange: (mode: number) => void } const FALLBACK_CLASSES: DetectionClass[] = [0, 20, 40].flatMap(modeOffset => FALLBACK_CLASS_NAMES.map((name, i) => ({ id: i + modeOffset, name, shortName: name.slice(0, 3), color: getClassColor(i), maxSizeM: 10, photoMode: modeOffset, })), ) export default function DetectionClasses({ selectedClassNum, onSelect, photoMode, onPhotoModeChange }: Props) { const { t } = useTranslation() const [classes, setClasses] = useState([]) useEffect(() => { api.get(endpoints.annotations.classes()) .then(list => setClasses(list?.length ? list : FALLBACK_CLASSES)) .catch(() => setClasses(FALLBACK_CLASSES)) }, []) useEffect(() => { const handler = (e: KeyboardEvent) => { const num = parseInt(e.key) if (num >= 1 && num <= 9) { const idx = num - 1 const cls = classes[idx + photoMode] if (cls) onSelect(cls.id) } } window.addEventListener('keydown', handler) return () => window.removeEventListener('keydown', handler) }, [classes, photoMode, onSelect]) // Auto-select first class of current photoMode when mode changes or classes load useEffect(() => { const modeClasses = classes.filter(c => c.photoMode === photoMode) const currentIsInMode = modeClasses.some(c => c.id === selectedClassNum) if (!currentIsInMode && modeClasses.length > 0) { onSelect(modeClasses[0].id) } }, [classes, photoMode, selectedClassNum, onSelect]) const modeClasses = classes.filter(c => c.photoMode === photoMode) const modes = [ { value: 0, label: t('annotations.regular') }, { value: 20, label: t('annotations.winter') }, { value: 40, label: t('annotations.night') }, ] return (
{/* Section header */}
{t('annotations.classes')} {modeClasses.length.toString().padStart(2, '0')}
{/* Column headers */}
{t('annotations.colNum')} {t('annotations.colName')} {t('annotations.colKey')}
{/* Class rows */}
{modeClasses.map((c, i) => { const isActive = selectedClassNum === c.id return (
onSelect(c.id)} onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') onSelect(c.id) }} className={`class-row${isActive ? ' active' : ''}`} > {c.name} {i + 1}
) })}
{/* PhotoMode segmented control */}
{t('annotations.photoMode')}
{modes.map(m => ( ))}
) }