backend-lehrer (5 files): - alerts_agent/db/repository.py (992 → 5), abitur_docs_api.py (956 → 3) - teacher_dashboard_api.py (951 → 3), services/pdf_service.py (916 → 3) - mail/mail_db.py (987 → 6) klausur-service (5 files): - legal_templates_ingestion.py (942 → 3), ocr_pipeline_postprocess.py (929 → 4) - ocr_pipeline_words.py (876 → 3), ocr_pipeline_ocr_merge.py (616 → 2) - KorrekturPage.tsx (956 → 6) website (5 pages): - mail (985 → 9), edu-search (958 → 8), mac-mini (950 → 7) - ocr-labeling (946 → 7), audit-workspace (871 → 4) studio-v2 (5 files + 1 deleted): - page.tsx (946 → 5), MessagesContext.tsx (925 → 4) - korrektur (914 → 6), worksheet-cleanup (899 → 6) - useVocabWorksheet.ts (888 → 3) - Deleted dead page-original.tsx (934 LOC) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
128 lines
5.7 KiB
TypeScript
128 lines
5.7 KiB
TypeScript
'use client'
|
|
|
|
import { GlassCard } from './GlassCard'
|
|
import { ProgressRing } from './ProgressRing'
|
|
|
|
interface PreviewResult {
|
|
has_handwriting: boolean
|
|
confidence: number
|
|
handwriting_ratio: number
|
|
image_width: number
|
|
image_height: number
|
|
estimated_times_ms: {
|
|
detection: number
|
|
inpainting: number
|
|
reconstruction: number
|
|
total: number
|
|
}
|
|
}
|
|
|
|
interface PreviewStepProps {
|
|
previewResult: PreviewResult
|
|
previewUrl: string | null
|
|
maskUrl: string | null
|
|
removeHandwriting: boolean
|
|
reconstructLayout: boolean
|
|
isProcessing: boolean
|
|
onBack: () => void
|
|
onCleanup: () => void
|
|
onGetMask: () => void
|
|
}
|
|
|
|
export function PreviewStep({
|
|
previewResult, previewUrl, maskUrl,
|
|
removeHandwriting, reconstructLayout, isProcessing,
|
|
onBack, onCleanup, onGetMask
|
|
}: PreviewStepProps) {
|
|
return (
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<GlassCard delay={100}>
|
|
<h3 className="text-lg font-semibold text-white mb-6">Analyse</h3>
|
|
<div className="flex justify-around">
|
|
<ProgressRing
|
|
progress={previewResult.confidence * 100}
|
|
label="Konfidenz"
|
|
value={`${Math.round(previewResult.confidence * 100)}%`}
|
|
color={previewResult.has_handwriting ? '#f97316' : '#22c55e'}
|
|
/>
|
|
<ProgressRing
|
|
progress={previewResult.handwriting_ratio * 100 * 10}
|
|
label="Handschrift"
|
|
value={`${(previewResult.handwriting_ratio * 100).toFixed(1)}%`}
|
|
color="#a78bfa"
|
|
/>
|
|
</div>
|
|
<div className={`mt-6 p-4 rounded-xl text-center ${
|
|
previewResult.has_handwriting ? 'bg-orange-500/20 text-orange-300' : 'bg-green-500/20 text-green-300'
|
|
}`}>
|
|
{previewResult.has_handwriting ? 'Handschrift erkannt' : 'Keine Handschrift gefunden'}
|
|
</div>
|
|
</GlassCard>
|
|
|
|
<GlassCard delay={200}>
|
|
<h3 className="text-lg font-semibold text-white mb-4">Geschätzte Zeit</h3>
|
|
<div className="space-y-3">
|
|
<div className="flex justify-between text-white/70">
|
|
<span>Erkennung</span>
|
|
<span className="text-white">~{Math.round(previewResult.estimated_times_ms.detection / 1000)}s</span>
|
|
</div>
|
|
{removeHandwriting && previewResult.has_handwriting && (
|
|
<div className="flex justify-between text-white/70">
|
|
<span>Bereinigung</span>
|
|
<span className="text-white">~{Math.round(previewResult.estimated_times_ms.inpainting / 1000)}s</span>
|
|
</div>
|
|
)}
|
|
{reconstructLayout && (
|
|
<div className="flex justify-between text-white/70">
|
|
<span>Layout</span>
|
|
<span className="text-white">~{Math.round(previewResult.estimated_times_ms.reconstruction / 1000)}s</span>
|
|
</div>
|
|
)}
|
|
<div className="flex justify-between pt-3 border-t border-white/10 font-medium">
|
|
<span className="text-white">Gesamt</span>
|
|
<span className="text-purple-300">~{Math.round(previewResult.estimated_times_ms.total / 1000)}s</span>
|
|
</div>
|
|
</div>
|
|
</GlassCard>
|
|
|
|
<GlassCard delay={300}>
|
|
<h3 className="text-lg font-semibold text-white mb-4">Bild-Info</h3>
|
|
<div className="space-y-3">
|
|
<div className="flex justify-between text-white/70"><span>Breite</span><span className="text-white">{previewResult.image_width}px</span></div>
|
|
<div className="flex justify-between text-white/70"><span>Höhe</span><span className="text-white">{previewResult.image_height}px</span></div>
|
|
<div className="flex justify-between text-white/70"><span>Pixel</span><span className="text-white">{(previewResult.image_width * previewResult.image_height / 1000000).toFixed(1)}MP</span></div>
|
|
</div>
|
|
<button onClick={onGetMask}
|
|
className="w-full mt-4 px-4 py-2 rounded-xl bg-white/10 text-white/70 hover:bg-white/20 hover:text-white transition-all text-sm">
|
|
Maske anzeigen
|
|
</button>
|
|
</GlassCard>
|
|
|
|
<GlassCard className="col-span-1 lg:col-span-2" delay={400}>
|
|
<h3 className="text-lg font-semibold text-white mb-4">Original</h3>
|
|
{previewUrl && <img src={previewUrl} alt="Original" className="w-full max-h-96 object-contain rounded-xl" />}
|
|
</GlassCard>
|
|
|
|
{maskUrl && (
|
|
<GlassCard delay={500}>
|
|
<h3 className="text-lg font-semibold text-white mb-4">Maske</h3>
|
|
<img src={maskUrl} alt="Mask" className="w-full max-h-96 object-contain rounded-xl" />
|
|
</GlassCard>
|
|
)}
|
|
|
|
<div className="col-span-1 lg:col-span-3 flex justify-center gap-4">
|
|
<button onClick={onBack}
|
|
className="px-6 py-3 rounded-xl bg-white/10 text-white hover:bg-white/20 transition-all flex items-center gap-2">
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" /></svg>
|
|
Zurück
|
|
</button>
|
|
<button onClick={onCleanup} disabled={isProcessing}
|
|
className="px-8 py-3 rounded-xl font-semibold bg-gradient-to-r from-orange-500 to-red-500 text-white hover:shadow-lg hover:shadow-orange-500/30 transition-all disabled:opacity-50 flex items-center gap-2">
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" /></svg>
|
|
Bereinigen starten
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|