Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 45s
CI / test-go-edu-search (push) Successful in 43s
CI / test-python-klausur (push) Failing after 2m51s
CI / test-python-agent-core (push) Successful in 36s
CI / test-nodejs-website (push) Successful in 37s
SmartSpellChecker (klausur-service): - Language-aware OCR post-correction without LLMs - Dual-dictionary heuristic for EN/DE language detection - Context-based a/I disambiguation via bigram lookup - Multi-digit substitution (sch00l→school) - Cross-language guard (don't false-correct DE words in EN column) - Umlaut correction (Schuler→Schüler, uber→über) - Integrated into spell_review_entries_sync() pipeline - 31 tests, 9ms/100 corrections Vocab-worksheet refactoring (studio-v2): - Split 2337-line page.tsx into 14 files - Custom hook useVocabWorksheet.ts (all state + logic) - 9 components in components/ directory - types.ts, constants.ts for shared definitions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
40 lines
2.0 KiB
TypeScript
40 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
import React from 'react'
|
|
import type { VocabWorksheetHook } from '../types'
|
|
|
|
export function FullscreenPreview({ h }: { h: VocabWorksheetHook }) {
|
|
return (
|
|
<div className="fixed inset-0 z-50 bg-black/80 backdrop-blur-sm flex items-center justify-center" onClick={() => h.setShowFullPreview(false)}>
|
|
<button
|
|
onClick={() => h.setShowFullPreview(false)}
|
|
className="absolute top-4 right-4 p-2 rounded-full bg-white/10 hover:bg-white/20 text-white z-10 transition-colors"
|
|
>
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
<div className="max-w-[95vw] max-h-[95vh] overflow-auto" onClick={(e) => e.stopPropagation()}>
|
|
{h.directFile?.type.startsWith('image/') && h.directFilePreview && (
|
|
<img src={h.directFilePreview} alt="Original" className="max-w-none" />
|
|
)}
|
|
{h.directFile?.type === 'application/pdf' && h.directFilePreview && (
|
|
<iframe src={h.directFilePreview} className="border-0 rounded-xl bg-white" style={{ width: '90vw', height: '90vh' }} />
|
|
)}
|
|
{h.selectedMobileFile && !h.directFile && (
|
|
h.selectedMobileFile.type.startsWith('image/')
|
|
? <img src={h.selectedMobileFile.dataUrl} alt="Original" className="max-w-none" />
|
|
: <iframe src={h.selectedMobileFile.dataUrl} className="border-0 rounded-xl bg-white" style={{ width: '90vw', height: '90vh' }} />
|
|
)}
|
|
{h.selectedDocumentId && !h.directFile && !h.selectedMobileFile && (() => {
|
|
const doc = h.storedDocuments.find(d => d.id === h.selectedDocumentId)
|
|
if (!doc?.url) return null
|
|
return doc.type.startsWith('image/')
|
|
? <img src={doc.url} alt="Original" className="max-w-none" />
|
|
: <iframe src={doc.url} className="border-0 rounded-xl bg-white" style={{ width: '90vw', height: '90vh' }} />
|
|
})()}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|