'use client' import { useCallback, useEffect, useState } from 'react' import type { DewarpResult, DewarpGroundTruth } from '@/app/(admin)/ai/ocr-pipeline/types' import { DewarpControls } from './DewarpControls' import { ImageCompareView } from './ImageCompareView' const KLAUSUR_API = '/klausur-api' interface StepDewarpProps { sessionId: string | null onNext: () => void } export function StepDewarp({ sessionId, onNext }: StepDewarpProps) { const [dewarpResult, setDewarpResult] = useState(null) const [dewarping, setDewarping] = useState(false) const [applying, setApplying] = useState(false) const [showGrid, setShowGrid] = useState(true) const [error, setError] = useState(null) // Auto-trigger dewarp when component mounts with a sessionId useEffect(() => { if (!sessionId || dewarpResult) return const runDewarp = async () => { setDewarping(true) setError(null) try { const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/dewarp`, { method: 'POST', }) if (!res.ok) { const err = await res.json().catch(() => ({ detail: res.statusText })) throw new Error(err.detail || 'Entzerrung fehlgeschlagen') } const data: DewarpResult = await res.json() data.dewarped_image_url = `${KLAUSUR_API}${data.dewarped_image_url}` setDewarpResult(data) } catch (e) { setError(e instanceof Error ? e.message : 'Unbekannter Fehler') } finally { setDewarping(false) } } runDewarp() }, [sessionId, dewarpResult]) const handleManualDewarp = useCallback(async (shearDegrees: number) => { if (!sessionId) return setApplying(true) setError(null) try { const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/dewarp/manual`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ shear_degrees: shearDegrees }), }) if (!res.ok) throw new Error('Manuelle Entzerrung fehlgeschlagen') const data = await res.json() setDewarpResult((prev) => prev ? { ...prev, method_used: data.method_used, shear_degrees: data.shear_degrees, dewarped_image_url: `${KLAUSUR_API}${data.dewarped_image_url}?t=${Date.now()}`, } : null, ) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setApplying(false) } }, [sessionId]) const handleGroundTruth = useCallback(async (gt: DewarpGroundTruth) => { if (!sessionId) return try { await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/ground-truth/dewarp`, { 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 2: Entzerrung (Dewarp)

Bitte zuerst Schritt 1 (Begradigung) abschliessen.

) } const deskewedUrl = `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/deskewed` const dewarpedUrl = dewarpResult?.dewarped_image_url ?? null return (
{/* Loading indicator */} {dewarping && (
Entzerrung laeuft (beide Methoden)...
)} {/* Image comparison: deskewed (left) vs dewarped (right) */} {/* Controls */} setShowGrid((v) => !v)} onManualDewarp={handleManualDewarp} onGroundTruth={handleGroundTruth} onNext={onNext} isApplying={applying} /> {error && (
{error}
)}
) }