Website (14 monoliths split): - compliance/page.tsx (1,519 → 9), docs/audit (1,262 → 20) - quality (1,231 → 16), alerts (1,203 → 10), docs (1,202 → 11) - i18n.ts (1,173 → 8 language files) - unity-bridge (1,094 → 12), backlog (1,087 → 6) - training (1,066 → 8), rag (1,063 → 8) - Deleted index_original.ts (4,899 LOC dead backup) Studio-v2 (5 monoliths split): - meet/page.tsx (1,481 → 9), messages (1,166 → 9) - AlertsB2BContext.tsx (1,165 → 5 modules) - alerts-b2b/page.tsx (1,019 → 6), korrektur/archiv (1,001 → 6) All existing imports preserved. Zero new TypeScript errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
165 lines
7.1 KiB
TypeScript
165 lines
7.1 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { GlassCard } from './GlassCard'
|
|
import type { AbiturDokument } from './DokumentCard'
|
|
|
|
interface PreviewModalProps {
|
|
dokument: AbiturDokument | null
|
|
onClose: () => void
|
|
onUseAsTemplate: () => void
|
|
isDark: boolean
|
|
}
|
|
|
|
export function PreviewModal({ dokument, onClose, onUseAsTemplate, isDark }: PreviewModalProps) {
|
|
const [zoom, setZoom] = useState(100)
|
|
|
|
if (!dokument) return null
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex">
|
|
{/* Backdrop */}
|
|
<div className="absolute inset-0 bg-black/70 backdrop-blur-sm" onClick={onClose} />
|
|
|
|
{/* Content */}
|
|
<div className="relative flex-1 flex m-4 gap-4">
|
|
{/* PDF Viewer */}
|
|
<div className="flex-1 flex flex-col">
|
|
<GlassCard className="flex-1 flex flex-col overflow-hidden" size="sm" isDark={isDark}>
|
|
{/* Toolbar */}
|
|
<div className={`flex items-center justify-between p-3 border-b ${isDark ? 'border-white/10' : 'border-slate-200'}`}>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={() => setZoom(z => Math.max(50, z - 25))}
|
|
className={`p-2 rounded-lg ${isDark ? 'hover:bg-white/10' : 'hover:bg-slate-100'}`}
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 12H4" />
|
|
</svg>
|
|
</button>
|
|
<span className={`text-sm ${isDark ? 'text-white/60' : 'text-slate-600'}`}>{zoom}%</span>
|
|
<button
|
|
onClick={() => setZoom(z => Math.min(200, z + 25))}
|
|
className={`p-2 rounded-lg ${isDark ? 'hover:bg-white/10' : 'hover:bg-slate-100'}`}
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<button
|
|
onClick={onClose}
|
|
className={`p-2 rounded-lg ${isDark ? 'hover:bg-white/10' : 'hover:bg-slate-100'}`}
|
|
>
|
|
<svg className="w-5 h-5" 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>
|
|
|
|
{/* PDF Content */}
|
|
<div className="flex-1 overflow-auto p-4">
|
|
<div
|
|
className="mx-auto bg-white rounded-lg shadow-xl"
|
|
style={{ width: `${zoom}%`, minHeight: '800px' }}
|
|
>
|
|
{dokument.preview_url ? (
|
|
<iframe
|
|
src={dokument.preview_url}
|
|
className="w-full h-full min-h-[800px]"
|
|
title={dokument.dateiname}
|
|
/>
|
|
) : (
|
|
<div className="flex items-center justify-center h-full text-slate-400">
|
|
<div className="text-center">
|
|
<svg className="w-16 h-16 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
<p>Vorschau nicht verfuegbar</p>
|
|
<a
|
|
href={dokument.download_url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-purple-400 hover:underline mt-2 inline-block"
|
|
>
|
|
PDF herunterladen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</GlassCard>
|
|
</div>
|
|
|
|
{/* Sidebar */}
|
|
<div className="w-80 flex flex-col gap-4">
|
|
{/* Close Button - prominent */}
|
|
<button
|
|
onClick={onClose}
|
|
className={`flex items-center gap-2 px-4 py-3 rounded-2xl font-medium transition-colors ${
|
|
isDark
|
|
? 'bg-white/10 text-white hover:bg-white/20'
|
|
: 'bg-white/70 text-slate-700 hover:bg-white/90'
|
|
}`}
|
|
style={{
|
|
backdropFilter: 'blur(24px)',
|
|
border: isDark ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(0,0,0,0.1)',
|
|
}}
|
|
>
|
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
|
</svg>
|
|
Zurueck zum Archiv
|
|
</button>
|
|
|
|
<GlassCard size="md" isDark={isDark}>
|
|
<h3 className={`font-semibold mb-4 ${isDark ? 'text-white' : 'text-slate-900'}`}>Details</h3>
|
|
<div className="space-y-3">
|
|
{[
|
|
{ label: 'Fach', value: dokument.fach },
|
|
{ label: 'Jahr', value: String(dokument.jahr) },
|
|
{ label: 'Bundesland', value: dokument.bundesland },
|
|
{ label: 'Niveau', value: dokument.niveau },
|
|
].map(({ label, value }) => (
|
|
<div key={label}>
|
|
<span className={`text-xs ${isDark ? 'text-white/50' : 'text-slate-500'}`}>{label}</span>
|
|
<p className={isDark ? 'text-white' : 'text-slate-900'}>{value}</p>
|
|
</div>
|
|
))}
|
|
{dokument.thema && (
|
|
<div>
|
|
<span className={`text-xs ${isDark ? 'text-white/50' : 'text-slate-500'}`}>Thema</span>
|
|
<p className={isDark ? 'text-white' : 'text-slate-900'}>{dokument.thema}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</GlassCard>
|
|
|
|
<GlassCard size="md" isDark={isDark}>
|
|
<h3 className={`font-semibold mb-4 ${isDark ? 'text-white' : 'text-slate-900'}`}>Aktionen</h3>
|
|
<div className="space-y-2">
|
|
<button
|
|
onClick={onUseAsTemplate}
|
|
className="w-full px-4 py-3 rounded-xl bg-gradient-to-r from-purple-500 to-pink-500 text-white font-semibold hover:shadow-lg hover:shadow-purple-500/30 transition-all"
|
|
>
|
|
Als Vorlage verwenden
|
|
</button>
|
|
<a
|
|
href={dokument.download_url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className={`block w-full px-4 py-3 rounded-xl text-center font-medium transition-colors ${
|
|
isDark ? 'bg-white/10 text-white hover:bg-white/20' : 'bg-slate-100 text-slate-700 hover:bg-slate-200'
|
|
}`}
|
|
>
|
|
Herunterladen
|
|
</a>
|
|
</div>
|
|
</GlassCard>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|