'use client' import { useEffect, useState } from 'react' import { getModules, getMatrix, getAssignments, getStats, getDeadlines, getModuleMedia, getAuditLog, generateContent, generateQuiz, publishContent, checkEscalation, getContent, generateAllContent, generateAllQuizzes, createModule, updateModule, deleteModule, deleteMatrixEntry, setMatrixEntry, startAssignment, completeAssignment, updateAssignment, listBlockConfigs, createBlockConfig, deleteBlockConfig, previewBlock, generateBlock, getCanonicalMeta, generateInteractiveVideo, } from '@/lib/sdk/training/api' import type { TrainingModule, TrainingAssignment, MatrixResponse, TrainingStats, DeadlineInfo, AuditLogEntry, ModuleContent, TrainingMedia, TrainingBlockConfig, CanonicalControlMeta, BlockPreview, BlockGenerateResult, } from '@/lib/sdk/training/types' import { REGULATION_LABELS, REGULATION_COLORS, FREQUENCY_LABELS, STATUS_LABELS, STATUS_COLORS, ROLE_LABELS, ALL_ROLES, TARGET_AUDIENCE_LABELS } from '@/lib/sdk/training/types' import { OverviewTab } from './_components/OverviewTab' import { ModulesTab } from './_components/ModulesTab' import { MatrixTab } from './_components/MatrixTab' import { AssignmentsTab } from './_components/AssignmentsTab' import { ContentTab } from './_components/ContentTab' import { AuditTab } from './_components/AuditTab' import { BlocksSection } from './_components/BlocksSection' import { ModuleCreateModal } from './_components/ModuleCreateModal' import { ModuleEditDrawer } from './_components/ModuleEditDrawer' import { MatrixAddModal } from './_components/MatrixAddModal' import { AssignmentDetailDrawer } from './_components/AssignmentDetailDrawer' type Tab = 'overview' | 'modules' | 'matrix' | 'assignments' | 'content' | 'audit' const TABS: { id: Tab; label: string }[] = [ { id: 'overview', label: 'Uebersicht' }, { id: 'modules', label: 'Modulkatalog' }, { id: 'matrix', label: 'Training Matrix' }, { id: 'assignments', label: 'Zuweisungen' }, { id: 'content', label: 'Content-Generator' }, { id: 'audit', label: 'Audit Trail' }, ] export default function TrainingPage() { const [activeTab, setActiveTab] = useState('overview') const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [stats, setStats] = useState(null) const [modules, setModules] = useState([]) const [matrix, setMatrix] = useState(null) const [assignments, setAssignments] = useState([]) const [deadlines, setDeadlines] = useState([]) const [auditLog, setAuditLog] = useState([]) const [selectedModuleId, setSelectedModuleId] = useState('') const [generatedContent, setGeneratedContent] = useState(null) const [generating, setGenerating] = useState(false) const [bulkGenerating, setBulkGenerating] = useState(false) const [bulkResult, setBulkResult] = useState<{ generated: number; skipped: number; errors: string[] } | null>(null) const [moduleMedia, setModuleMedia] = useState([]) const [interactiveGenerating, setInteractiveGenerating] = useState(false) const [statusFilter, setStatusFilter] = useState('') const [regulationFilter, setRegulationFilter] = useState('') const [showModuleCreate, setShowModuleCreate] = useState(false) const [selectedModule, setSelectedModule] = useState(null) const [matrixAddRole, setMatrixAddRole] = useState(null) const [selectedAssignment, setSelectedAssignment] = useState(null) const [escalationResult, setEscalationResult] = useState<{ total_checked: number; escalated: number } | null>(null) const [blocks, setBlocks] = useState([]) const [canonicalMeta, setCanonicalMeta] = useState(null) const [showBlockCreate, setShowBlockCreate] = useState(false) const [blockPreview, setBlockPreview] = useState(null) const [blockPreviewId, setBlockPreviewId] = useState('') const [blockGenerating, setBlockGenerating] = useState(false) const [blockResult, setBlockResult] = useState(null) useEffect(() => { loadData() }, []) useEffect(() => { if (selectedModuleId) loadModuleMedia(selectedModuleId) }, [selectedModuleId]) async function loadData() { setLoading(true); setError(null) try { const [statsRes, modulesRes, matrixRes, assignmentsRes, deadlinesRes, auditRes, blocksRes, metaRes] = await Promise.allSettled([ getStats(), getModules(), getMatrix(), getAssignments({ limit: 50 }), getDeadlines(10), getAuditLog({ limit: 30 }), listBlockConfigs(), getCanonicalMeta(), ]) if (statsRes.status === 'fulfilled') setStats(statsRes.value) if (modulesRes.status === 'fulfilled') setModules(modulesRes.value.modules) if (matrixRes.status === 'fulfilled') setMatrix(matrixRes.value) if (assignmentsRes.status === 'fulfilled') setAssignments(assignmentsRes.value.assignments) if (deadlinesRes.status === 'fulfilled') setDeadlines(deadlinesRes.value.deadlines) if (auditRes.status === 'fulfilled') setAuditLog(auditRes.value.entries) if (blocksRes.status === 'fulfilled') setBlocks(blocksRes.value.blocks) if (metaRes.status === 'fulfilled') setCanonicalMeta(metaRes.value) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler beim Laden') } finally { setLoading(false) } } async function loadModuleMedia(moduleId: string) { try { const r = await getModuleMedia(moduleId); setModuleMedia(r.media) } catch { setModuleMedia([]) } } async function handleGenerateContent() { if (!selectedModuleId) return; setGenerating(true) try { setGeneratedContent(await generateContent(selectedModuleId)) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setGenerating(false) } } async function handleGenerateQuiz() { if (!selectedModuleId) return; setGenerating(true) try { await generateQuiz(selectedModuleId, 5); await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setGenerating(false) } } async function handleGenerateInteractiveVideo() { if (!selectedModuleId) return; setInteractiveGenerating(true) try { await generateInteractiveVideo(selectedModuleId); await loadModuleMedia(selectedModuleId) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setInteractiveGenerating(false) } } async function handlePublishContent(contentId: string) { try { await publishContent(contentId); setGeneratedContent(null); await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handleCheckEscalation() { try { const r = await checkEscalation() setEscalationResult({ total_checked: r.total_checked, escalated: r.escalated }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handleDeleteMatrixEntry(roleCode: string, moduleId: string) { if (!window.confirm('Modulzuordnung entfernen?')) return try { await deleteMatrixEntry(roleCode, moduleId); await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handleLoadContent(moduleId: string) { try { setGeneratedContent(await getContent(moduleId)) } catch { setGeneratedContent(null) } } async function handleBulkContent() { setBulkGenerating(true); setBulkResult(null) try { const r = await generateAllContent('de') setBulkResult({ generated: r.generated ?? 0, skipped: r.skipped ?? 0, errors: r.errors ?? [] }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setBulkGenerating(false) } } async function handleBulkQuiz() { setBulkGenerating(true); setBulkResult(null) try { const r = await generateAllQuizzes() setBulkResult({ generated: r.generated ?? 0, skipped: r.skipped ?? 0, errors: r.errors ?? [] }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setBulkGenerating(false) } } async function handleCreateBlock(data: Parameters[0]) { try { await createBlockConfig(data); setShowBlockCreate(false); const r = await listBlockConfigs(); setBlocks(r.blocks) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handleDeleteBlock(id: string) { if (!confirm('Block-Konfiguration wirklich loeschen?')) return try { await deleteBlockConfig(id); const r = await listBlockConfigs(); setBlocks(r.blocks) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handlePreviewBlock(id: string) { setBlockPreviewId(id); setBlockPreview(null); setBlockResult(null) try { setBlockPreview(await previewBlock(id)) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } async function handleGenerateBlock(id: string) { setBlockGenerating(true); setBlockResult(null) try { setBlockResult(await generateBlock(id, { language: 'de', auto_matrix: true })); await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setBlockGenerating(false) } } const filteredModules = modules.filter(m => !regulationFilter || m.regulation_area === regulationFilter) const filteredAssignments = assignments.filter(a => !statusFilter || a.status === statusFilter) if (loading) return (
{[1,2,3,4].map(i =>
)}
) return (

Compliance Training Engine

Training-Module, Zuweisungen und Compliance-Schulungen verwalten

{error && (
{error}
)}
{activeTab === 'overview' && stats && ( setEscalationResult(null)} /> )} {activeTab === 'modules' && ( setShowModuleCreate(true)} onModuleClick={setSelectedModule} /> )} {activeTab === 'matrix' && matrix && ( )} {activeTab === 'assignments' && ( )} {activeTab === 'content' && (
{ setSelectedModuleId(id); setGeneratedContent(null); setModuleMedia([]); if (id) { handleLoadContent(id); loadModuleMedia(id) } }} generatedContent={generatedContent} generating={generating} bulkGenerating={bulkGenerating} bulkResult={bulkResult} moduleMedia={moduleMedia} interactiveGenerating={interactiveGenerating} onGenerateContent={handleGenerateContent} onGenerateQuiz={handleGenerateQuiz} onBulkContent={handleBulkContent} onBulkQuiz={handleBulkQuiz} onPublishContent={handlePublishContent} onReloadMedia={() => loadModuleMedia(selectedModuleId)} onGenerateInteractiveVideo={handleGenerateInteractiveVideo} />
)} {activeTab === 'audit' && } {showModuleCreate && setShowModuleCreate(false)} onSaved={() => { setShowModuleCreate(false); loadData() }} />} {selectedModule && setSelectedModule(null)} onSaved={() => { setSelectedModule(null); loadData() }} />} {matrixAddRole && setMatrixAddRole(null)} onSaved={() => { setMatrixAddRole(null); loadData() }} />} {selectedAssignment && setSelectedAssignment(null)} onSaved={() => { setSelectedAssignment(null); loadData() }} />}
) }