Files
breakpilot-lehrer/website/app/admin/magic-help/_components/OcrTestTab.tsx
Benjamin Admin 6811264756 [split-required] Split final batch of monoliths >1000 LOC
Python (6 files in klausur-service):
- rbac.py (1,132 → 4), admin_api.py (1,012 → 4)
- routes/eh.py (1,111 → 4), ocr_pipeline_geometry.py (1,105 → 5)

Python (2 files in backend-lehrer):
- unit_api.py (1,226 → 6), game_api.py (1,129 → 5)

Website (6 page files):
- 4x klausur-korrektur pages (1,249-1,328 LOC each) → shared components
  in website/components/klausur-korrektur/ (17 shared files)
- companion (1,057 → 10), magic-help (1,017 → 8)

All re-export barrels preserve backward compatibility.
Zero import errors verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 23:17:30 +02:00

105 lines
4.7 KiB
TypeScript

'use client'
import type { OCRResult } from './types'
interface OcrTestTabProps {
ocrResult: OCRResult | null
ocrLoading: boolean
handleFileUpload: (file: File) => void
}
export default function OcrTestTab({ ocrResult, ocrLoading, handleFileUpload }: OcrTestTabProps) {
return (
<div className="space-y-6">
{/* OCR Test */}
<div className="bg-gray-800/50 border border-gray-700 rounded-xl p-6">
<h2 className="text-lg font-semibold text-white mb-4">OCR Test</h2>
<p className="text-sm text-gray-400 mb-4">
Teste die Handschrifterkennung mit einem eigenen Bild. Das Ergebnis zeigt
den erkannten Text, Konfidenz und Verarbeitungszeit.
</p>
<div
className="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center cursor-pointer hover:border-blue-500 transition-colors"
onClick={() => document.getElementById('ocr-file-input')?.click()}
onDragOver={(e) => { e.preventDefault(); e.currentTarget.classList.add('border-blue-500') }}
onDragLeave={(e) => { e.currentTarget.classList.remove('border-blue-500') }}
onDrop={(e) => {
e.preventDefault()
e.currentTarget.classList.remove('border-blue-500')
const file = e.dataTransfer.files[0]
if (file?.type.startsWith('image/')) handleFileUpload(file)
}}
>
<div className="text-4xl mb-2">📄</div>
<div className="text-gray-300">Bild hierher ziehen oder klicken zum Hochladen</div>
<div className="text-xs text-gray-500 mt-1">PNG, JPG - Handgeschriebener Text</div>
</div>
<input
type="file"
id="ocr-file-input"
accept="image/*"
className="hidden"
onChange={(e) => {
const file = e.target.files?.[0]
if (file) handleFileUpload(file)
}}
/>
{ocrLoading && (
<div className="mt-4 flex items-center gap-2 text-gray-400">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
Analysiere Bild...
</div>
)}
{ocrResult && (
<div className="mt-4 bg-gray-900/50 rounded-lg p-4">
<h3 className="text-sm font-medium text-gray-300 mb-2">Erkannter Text:</h3>
<pre className="bg-gray-950 p-3 rounded text-sm text-white whitespace-pre-wrap max-h-48 overflow-y-auto">
{ocrResult.text || '(Kein Text erkannt)'}
</pre>
<div className="mt-3 grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div className="bg-gray-800 rounded p-2">
<div className="text-gray-400 text-xs">Konfidenz</div>
<div className="text-white font-medium">{(ocrResult.confidence * 100).toFixed(1)}%</div>
</div>
<div className="bg-gray-800 rounded p-2">
<div className="text-gray-400 text-xs">Verarbeitungszeit</div>
<div className="text-white font-medium">{ocrResult.processing_time_ms}ms</div>
</div>
<div className="bg-gray-800 rounded p-2">
<div className="text-gray-400 text-xs">Modell</div>
<div className="text-white font-medium">{ocrResult.model || 'TrOCR'}</div>
</div>
<div className="bg-gray-800 rounded p-2">
<div className="text-gray-400 text-xs">LoRA Adapter</div>
<div className="text-white font-medium">{ocrResult.has_lora_adapter ? 'Ja' : 'Nein'}</div>
</div>
</div>
</div>
)}
</div>
{/* Confidence Interpretation */}
<div className="bg-gray-800/50 border border-gray-700 rounded-xl p-6">
<h2 className="text-lg font-semibold text-white mb-4">Konfidenz-Interpretation</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-green-900/20 border border-green-800 rounded-lg p-4">
<div className="text-green-400 font-medium">90-100%</div>
<div className="text-sm text-gray-300 mt-1">Sehr hohe Sicherheit - Text kann direkt übernommen werden</div>
</div>
<div className="bg-yellow-900/20 border border-yellow-800 rounded-lg p-4">
<div className="text-yellow-400 font-medium">70-90%</div>
<div className="text-sm text-gray-300 mt-1">Gute Sicherheit - manuelle Überprüfung empfohlen</div>
</div>
<div className="bg-red-900/20 border border-red-800 rounded-lg p-4">
<div className="text-red-400 font-medium">&lt; 70%</div>
<div className="text-sm text-gray-300 mt-1">Niedrige Sicherheit - manuelle Eingabe erforderlich</div>
</div>
</div>
</div>
</div>
)
}