'use client' import type { TrainingModule, TrainingBlockConfig, CanonicalControlMeta, BlockPreview, BlockGenerateResult, } from '@/lib/sdk/training/types' import { TARGET_AUDIENCE_LABELS, ROLE_LABELS, REGULATION_LABELS } from '@/lib/sdk/training/types' interface BlocksSectionProps { blocks: TrainingBlockConfig[] canonicalMeta: CanonicalControlMeta | null blockPreview: BlockPreview | null blockPreviewId: string blockGenerating: boolean blockResult: BlockGenerateResult | null showBlockCreate: boolean onShowBlockCreate: (show: boolean) => void onPreviewBlock: (id: string) => void onGenerateBlock: (id: string) => void onDeleteBlock: (id: string) => void onCreateBlock: (data: { name: string; description?: string; domain_filter?: string; category_filter?: string; severity_filter?: string; target_audience_filter?: string; regulation_area: string; module_code_prefix: string; max_controls_per_module?: number; }) => void } export function BlocksSection({ blocks, canonicalMeta, blockPreview, blockPreviewId, blockGenerating, blockResult, showBlockCreate, onShowBlockCreate, onPreviewBlock, onGenerateBlock, onDeleteBlock, onCreateBlock, }: BlocksSectionProps) { return (

Schulungsbloecke aus Controls

Canonical Controls nach Kriterien filtern und automatisch Schulungsmodule generieren {canonicalMeta && ({canonicalMeta.total} Controls verfuegbar)}

{blocks.length > 0 ? (
{blocks.map(block => ( ))}
Name Domain Zielgruppe Severity Prefix Letzte Generierung Aktionen
{block.name}
{block.description &&
{block.description}
}
{block.domain_filter || 'Alle'} {block.target_audience_filter ? (TARGET_AUDIENCE_LABELS[block.target_audience_filter] || block.target_audience_filter) : 'Alle'} {block.severity_filter || 'Alle'} {block.module_code_prefix} {block.last_generated_at ? new Date(block.last_generated_at).toLocaleString('de-DE') : 'Noch nie'}
) : (
Noch keine Schulungsbloecke konfiguriert. Erstelle einen Block, um Controls automatisch in Module umzuwandeln.
)} {blockPreview && blockPreviewId && (

Preview: {blocks.find(b => b.id === blockPreviewId)?.name}

Controls: {blockPreview.control_count} Module: {blockPreview.module_count} Rollen: {blockPreview.proposed_roles.map(r => ROLE_LABELS[r] || r).join(', ')}
{blockPreview.controls.length > 0 && (
Passende Controls anzeigen ({blockPreview.control_count})
{blockPreview.controls.slice(0, 50).map(ctrl => (
{ctrl.control_id} {ctrl.title} {ctrl.severity}
))} {blockPreview.control_count > 50 &&
... und {blockPreview.control_count - 50} weitere
}
)}
)} {blockResult && (

Generierung abgeschlossen

Module erstellt: {blockResult.modules_created} Controls verknuepft: {blockResult.controls_linked} Matrix-Eintraege: {blockResult.matrix_entries_created} Content generiert: {blockResult.content_generated}
{blockResult.errors && blockResult.errors.length > 0 && (
{blockResult.errors.map((err, i) =>
{err}
)}
)}
)} {showBlockCreate && ( onShowBlockCreate(false)} /> )}
) } function BlockCreateModal({ canonicalMeta, onSubmit, onClose, }: { canonicalMeta: CanonicalControlMeta | null onSubmit: BlocksSectionProps['onCreateBlock'] onClose: () => void }) { return (

Neuen Schulungsblock erstellen

{ e.preventDefault() const fd = new FormData(e.currentTarget) onSubmit({ name: fd.get('name') as string, description: fd.get('description') as string || undefined, domain_filter: fd.get('domain_filter') as string || undefined, category_filter: fd.get('category_filter') as string || undefined, severity_filter: fd.get('severity_filter') as string || undefined, target_audience_filter: fd.get('target_audience_filter') as string || undefined, regulation_area: fd.get('regulation_area') as string, module_code_prefix: fd.get('module_code_prefix') as string, max_controls_per_module: parseInt(fd.get('max_controls_per_module') as string) || 20, }) }} className="space-y-3">