'use client' import { useCallback, useEffect, useState } from 'react' import type { ColumnResult, ColumnGroundTruth } from '@/app/(admin)/ai/ocr-pipeline/types' import { ColumnControls } from './ColumnControls' const KLAUSUR_API = '/klausur-api' interface StepColumnDetectionProps { sessionId: string | null onNext: () => void } export function StepColumnDetection({ sessionId, onNext }: StepColumnDetectionProps) { const [columnResult, setColumnResult] = useState(null) const [detecting, setDetecting] = useState(false) const [error, setError] = useState(null) // Auto-trigger column detection on mount useEffect(() => { if (!sessionId || columnResult) return const runDetection = async () => { setDetecting(true) setError(null) try { // First check if columns already detected (reload case) const infoRes = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}`) if (infoRes.ok) { const info = await infoRes.json() if (info.column_result) { setColumnResult(info.column_result) setDetecting(false) return } } // Run detection const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/columns`, { method: 'POST', }) if (!res.ok) { const err = await res.json().catch(() => ({ detail: res.statusText })) throw new Error(err.detail || 'Spaltenerkennung fehlgeschlagen') } const data: ColumnResult = await res.json() setColumnResult(data) } catch (e) { setError(e instanceof Error ? e.message : 'Unbekannter Fehler') } finally { setDetecting(false) } } runDetection() }, [sessionId, columnResult]) const handleRerun = useCallback(async () => { if (!sessionId) return setDetecting(true) setError(null) try { const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/columns`, { method: 'POST', }) if (!res.ok) throw new Error('Spaltenerkennung fehlgeschlagen') const data: ColumnResult = await res.json() setColumnResult(data) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setDetecting(false) } }, [sessionId]) const handleGroundTruth = useCallback(async (gt: ColumnGroundTruth) => { if (!sessionId) return try { await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/ground-truth/columns`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(gt), }) } catch (e) { console.error('Ground truth save failed:', e) } }, [sessionId]) if (!sessionId) { return (
📊

Schritt 3: Spaltenerkennung

Bitte zuerst Schritt 1 und 2 abschliessen.

) } const dewarpedUrl = `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/dewarped` const overlayUrl = `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/columns-overlay` return (
{/* Loading indicator */} {detecting && (
Spaltenerkennung laeuft...
)} {/* Image comparison: overlay (left) vs clean (right) */}
Mit Spalten-Overlay
{columnResult ? ( // eslint-disable-next-line @next/next/no-img-element Spalten-Overlay ) : (
{detecting ? 'Erkenne Spalten...' : 'Keine Daten'}
)}
Entzerrtes Bild
{/* eslint-disable-next-line @next/next/no-img-element */} Entzerrt
{/* Controls */} {error && (
{error}
)}
) }