Phase 1 — Python (klausur-service): 5 monoliths → 36 files - dsfa_corpus_ingestion.py (1,828 LOC → 5 files) - cv_ocr_engines.py (2,102 LOC → 7 files) - cv_layout.py (3,653 LOC → 10 files) - vocab_worksheet_api.py (2,783 LOC → 8 files) - grid_build_core.py (1,958 LOC → 6 files) Phase 2 — Go (edu-search-service, school-service): 8 monoliths → 19 files - staff_crawler.go (1,402 → 4), policy/store.go (1,168 → 3) - policy_handlers.go (700 → 2), repository.go (684 → 2) - search.go (592 → 2), ai_extraction_handlers.go (554 → 2) - seed_data.go (591 → 2), grade_service.go (646 → 2) Phase 3 — TypeScript (admin-lehrer): 45 monoliths → 220+ files - sdk/types.ts (2,108 → 16 domain files) - ai/rag/page.tsx (2,686 → 14 files) - 22 page.tsx files split into _components/ + _hooks/ - 11 component files split into sub-components - 10 SDK data catalogs added to loc-exceptions - Deleted dead backup index_original.ts (4,899 LOC) All original public APIs preserved via re-export facades. Zero new errors: Python imports verified, Go builds clean, TypeScript tsc --noEmit shows only pre-existing errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
139 lines
4.4 KiB
TypeScript
139 lines
4.4 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* Klausur-Korrektur Admin Page
|
|
*
|
|
* Hauptseite fuer die KI-gestuetzte Abitur-Korrektur.
|
|
* Zeigt alle Klausuren und ermoeglicht das Erstellen neuer Klausuren.
|
|
*/
|
|
|
|
import { tabs } from './_components/constants'
|
|
import { useKlausurKorrektur } from './_components/useKlausurKorrektur'
|
|
import { KlausurenTab } from './_components/KlausurenTab'
|
|
import { ErstellenTab } from './_components/ErstellenTab'
|
|
import { WillkommenTab } from './_components/WillkommenTab'
|
|
import { DirektuploadTab } from './_components/DirektuploadTab'
|
|
import { StatistikenTab } from './_components/StatistikenTab'
|
|
|
|
export default function KlausurKorrekturPage() {
|
|
const {
|
|
activeTab,
|
|
setActiveTab,
|
|
klausuren,
|
|
loading,
|
|
error,
|
|
setError,
|
|
creating,
|
|
gradeInfo,
|
|
templates,
|
|
loadingTemplates,
|
|
form,
|
|
setForm,
|
|
ehForm,
|
|
setEhForm,
|
|
direktForm,
|
|
setDirektForm,
|
|
direktStep,
|
|
setDirektStep,
|
|
uploading,
|
|
handleCreateKlausur,
|
|
handleDeleteKlausur,
|
|
handleDirektupload,
|
|
markAsVisited,
|
|
} = useKlausurKorrektur()
|
|
|
|
return (
|
|
<div className="min-h-screen bg-slate-50">
|
|
<div className="max-w-7xl mx-auto px-4 py-6">
|
|
{/* Page header */}
|
|
<div className="mb-6">
|
|
<h1 className="text-2xl font-bold text-slate-800">Klausur-Korrektur</h1>
|
|
<p className="text-sm text-slate-500">KI-gestuetzte Abitur-Korrektur fuer Niedersachsen</p>
|
|
</div>
|
|
|
|
{/* Error display */}
|
|
{error && (
|
|
<div className="mb-4 p-4 bg-red-50 border border-red-200 rounded-lg flex items-center gap-3">
|
|
<svg className="w-5 h-5 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
<span className="text-red-800">{error}</span>
|
|
<button onClick={() => setError(null)} className="ml-auto text-red-600 hover:text-red-800">
|
|
<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>
|
|
)}
|
|
|
|
{/* Tab navigation */}
|
|
<div className="border-b border-slate-200 mb-6">
|
|
<nav className="flex gap-4">
|
|
{tabs.filter(tab => !tab.hidden).map((tab) => (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => {
|
|
if (tab.id !== 'willkommen') markAsVisited()
|
|
setActiveTab(tab.id)
|
|
}}
|
|
className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors ${
|
|
activeTab === tab.id
|
|
? 'border-purple-500 text-purple-600'
|
|
: 'border-transparent text-slate-500 hover:text-slate-700 hover:border-slate-300'
|
|
}`}
|
|
>
|
|
{tab.icon}
|
|
{tab.name}
|
|
</button>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
{/* Tab content */}
|
|
{activeTab === 'willkommen' && (
|
|
<WillkommenTab
|
|
klausuren={klausuren}
|
|
onNavigate={setActiveTab}
|
|
markAsVisited={markAsVisited}
|
|
/>
|
|
)}
|
|
{activeTab === 'klausuren' && (
|
|
<KlausurenTab
|
|
klausuren={klausuren}
|
|
loading={loading}
|
|
onDelete={handleDeleteKlausur}
|
|
onNavigate={setActiveTab}
|
|
/>
|
|
)}
|
|
{activeTab === 'erstellen' && (
|
|
<ErstellenTab
|
|
form={form}
|
|
setForm={setForm}
|
|
ehForm={ehForm}
|
|
setEhForm={setEhForm}
|
|
templates={templates}
|
|
loadingTemplates={loadingTemplates}
|
|
creating={creating}
|
|
onSubmit={handleCreateKlausur}
|
|
onNavigate={setActiveTab}
|
|
/>
|
|
)}
|
|
{activeTab === 'direktupload' && (
|
|
<DirektuploadTab
|
|
direktForm={direktForm}
|
|
setDirektForm={setDirektForm}
|
|
direktStep={direktStep}
|
|
setDirektStep={setDirektStep}
|
|
uploading={uploading}
|
|
onUpload={handleDirektupload}
|
|
onNavigate={setActiveTab}
|
|
/>
|
|
)}
|
|
{activeTab === 'statistiken' && (
|
|
<StatistikenTab klausuren={klausuren} gradeInfo={gradeInfo} />
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|