diff --git a/src/components/workers/WorkerCard.jsx b/src/components/workers/WorkerCard.jsx deleted file mode 100644 index ffb289a..0000000 --- a/src/components/workers/WorkerCard.jsx +++ /dev/null @@ -1,144 +0,0 @@ -import { useEffect, useRef } from 'react' -import { Link } from 'react-router-dom' -import Badge from '../ui/Badge' -import { counterLines, formatCount, formatUsd, safeLink, statusTone, tokenTotal, traceRows, workerStatusLabel } from '../../lib/workersView' -import { MODEL_IDS, hatForWorker, roleOf } from '../../lib/workersRoster' -import { drawWorker, setGrid } from './engine/sprites' - -const DASH = '–' - -// Modell-Chip je Hut (Wörterbuch statt zusammengesetzter Klasse: der CSS-Test in workers.css findet die Namen) -const CHIP = { - opus: 'wk-chip-opus', - sonnet: 'wk-chip-sonnet', - haiku: 'wk-chip-haiku', - overseer: 'wk-chip-overseer', -} - -const PORTRAIT_W = 72 -const PORTRAIT_H = 96 -// Beginnt die Karte tiefer als so viele Pixel über der Unterkante des Fensters, wird sie nach oben geholt -const MIN_VISIBLE = 120 - -const isRecord = (v) => v !== null && typeof v === 'object' && !Array.isArray(v) - -// Status aus dem Zustandseintrag; ein nicht angeschlossener Worker ist grau (wie in indexWorkers) -function statusOf(worker) { - if (!isRecord(worker)) return '' - return worker.connected === false ? 'grau' : worker.status -} - -// Porträt der Figur auf einem eigenen Canvas (Raster 4, Figur bei 6/8) -function Portrait({ hat, grey }) { - const ref = useRef(null) - useEffect(() => { - const canvas = ref.current - const ctx = canvas && canvas.getContext ? canvas.getContext('2d') : null - if (!ctx) return - ctx.clearRect(0, 0, PORTRAIT_W, PORTRAIT_H) - setGrid(ctx, { k: 4 }) - drawWorker(ctx, 6, 8, { hat, grey, scale: 1 }) - }, [hat, grey]) - return -} - -// Einziger Ort der Karte, an dem ein Ziel für einen Link entsteht: nur was safeLink durchlässt wird ein Link -// (extern in neuem Tab mit noopener, intern über den Router), alles andere bleibt Text. -function TraceText({ link, children }) { - const safe = link ? safeLink(link.href) : null - if (!safe) return <>{children}> - if (safe.external) return {children} - return {children} -} - -// Karte eines Workers: Porträt, Rolle, Modell, Status, Tageswerte und die letzten Aktionen. -// worker = Zustandseintrag (status, task, counters, connected), trace = Antwort von api.trace (oder null). -export default function WorkerCard({ workerId, worker, trace, loading, error, onClose }) { - const sectionRef = useRef(null) - const headingRef = useRef(null) - - // Neue Auswahl: Der Name nimmt den Fokus (Screenreader sagen die Karte an), und liegt der Kartenanfang außerhalb des Fensters, - // wird die Karte an den oberen Rand geholt. Auf Handy und Tablet steht die Karte über der langen Liste, aus der man wählt. - useEffect(() => { - if (!workerId) return - const heading = headingRef.current - if (heading && typeof heading.focus === 'function') heading.focus({ preventScroll: true }) - const section = sectionRef.current - if (!section || typeof section.scrollIntoView !== 'function') return - const top = section.getBoundingClientRect().top - const viewport = window.innerHeight || document.documentElement.clientHeight - const margin = parseFloat(window.getComputedStyle(section).scrollMarginTop) || 0 - if (top < margin || top > viewport - MIN_VISIBLE) section.scrollIntoView({ block: 'start' }) - }, [workerId]) - - if (!workerId) { - return ( -
Klicke eine Figur oder wähle einen Worker aus der Liste.
{roleText}
- {modelId && {modelId}} - {workerStatusLabel(status)} -
Spur wird geladen …
Noch keine Aktionen.
Die Worker hören sofort auf, bis jemand fortsetzt.