'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 { ContentTab } from './_components/ContentTab' import OverviewTab from './_components/OverviewTab' import ModulesTab from './_components/ModulesTab' import MatrixTab from './_components/MatrixTab' import AssignmentsTab from './_components/AssignmentsTab' import AuditTab from './_components/AuditTab' 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 result = await getModuleMedia(moduleId); setModuleMedia(result.media) } catch { setModuleMedia([]) } } async function handleGenerateContent() { if (!selectedModuleId) return setGenerating(true) try { const content = await generateContent(selectedModuleId); setGeneratedContent(content) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler bei der Content-Generierung') } 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 bei der Quiz-Generierung') } 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 bei der interaktiven Video-Generierung') } 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 beim Veroeffentlichen') } } async function handleCheckEscalation() { try { const result = await checkEscalation() setEscalationResult({ total_checked: result.total_checked, escalated: result.escalated }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler bei der Eskalationspruefung') } } 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 beim Entfernen') } } async function handleBulkContent() { setBulkGenerating(true); setBulkResult(null) try { const result = await generateAllContent('de') setBulkResult({ generated: result.generated ?? 0, skipped: result.skipped ?? 0, errors: result.errors ?? [] }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler bei der Bulk-Generierung') } finally { setBulkGenerating(false) } } async function handleBulkQuiz() { setBulkGenerating(true); setBulkResult(null) try { const result = await generateAllQuizzes() setBulkResult({ generated: result.generated ?? 0, skipped: result.skipped ?? 0, errors: result.errors ?? [] }) await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler bei der Bulk-Quiz-Generierung') } finally { setBulkGenerating(false) } } async function handleCreateBlock(data: Parameters[0]) { try { await createBlockConfig(data); setShowBlockCreate(false); const res = await listBlockConfigs(); setBlocks(res.blocks) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler beim Erstellen') } } async function handleDeleteBlock(id: string) { if (!confirm('Block-Konfiguration wirklich loeschen?')) return try { await deleteBlockConfig(id); const res = await listBlockConfigs(); setBlocks(res.blocks) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler beim Loeschen') } } async function handlePreviewBlock(id: string) { setBlockPreviewId(id); setBlockPreview(null); setBlockResult(null) try { const preview = await previewBlock(id); setBlockPreview(preview) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler beim Preview') } } async function handleGenerateBlock(id: string) { setBlockGenerating(true); setBlockResult(null) try { const result = await generateBlock(id, { language: 'de', auto_matrix: true }); setBlockResult(result); await loadData() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler bei der Block-Generierung') } finally { setBlockGenerating(false) } } const handleModuleSelect = (id: string) => { setSelectedModuleId(id); setGeneratedContent(null); setModuleMedia([]) if (id) { getContent(id).then(setGeneratedContent).catch(() => setGeneratedContent(null)) loadModuleMedia(id) } } 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' && ( !regulationFilter || m.regulation_area === regulationFilter)} regulationFilter={regulationFilter} onRegulationFilterChange={setRegulationFilter} onCreateClick={() => setShowModuleCreate(true)} onModuleClick={setSelectedModule} /> )} {activeTab === 'matrix' && matrix && ( )} {activeTab === 'assignments' && ( !statusFilter || a.status === statusFilter)} statusFilter={statusFilter} onStatusFilterChange={setStatusFilter} onAssignmentClick={setSelectedAssignment} /> )} {activeTab === 'content' && ( )} {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() }} />}
) }