Agent-completed splits committed after agents hit rate limits before committing their work. All 4 pages now under 500 LOC: - consent-management: 1303 -> 193 LOC (+ 7 _components, _hooks, _data, _types) - control-library: 1210 -> 298 LOC (+ _components, _types) - incidents: 1150 -> 373 LOC (+ _components) - training: 1127 -> 366 LOC (+ _components) Verification: next build clean (142 pages generated). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
118 lines
4.7 KiB
TypeScript
118 lines
4.7 KiB
TypeScript
'use client'
|
|
|
|
import { Zap, X, RefreshCw } from 'lucide-react'
|
|
|
|
export function GeneratorModal({
|
|
genDomain,
|
|
setGenDomain,
|
|
genMaxControls,
|
|
setGenMaxControls,
|
|
genDryRun,
|
|
setGenDryRun,
|
|
generating,
|
|
genResult,
|
|
onGenerate,
|
|
onClose,
|
|
}: {
|
|
genDomain: string
|
|
setGenDomain: (v: string) => void
|
|
genMaxControls: number
|
|
setGenMaxControls: (v: number) => void
|
|
genDryRun: boolean
|
|
setGenDryRun: (v: boolean) => void
|
|
generating: boolean
|
|
genResult: Record<string, unknown> | null
|
|
onGenerate: () => void
|
|
onClose: () => void
|
|
}) {
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
|
<div className="bg-white rounded-xl shadow-xl w-full max-w-lg p-6 mx-4">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-2">
|
|
<Zap className="w-5 h-5 text-amber-600" />
|
|
<h2 className="text-lg font-semibold text-gray-900">Control Generator</h2>
|
|
</div>
|
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className="block text-xs font-medium text-gray-600 mb-1">Domain (optional)</label>
|
|
<select value={genDomain} onChange={e => setGenDomain(e.target.value)} className="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg">
|
|
<option value="">Alle Domains</option>
|
|
<option value="AUTH">AUTH — Authentifizierung</option>
|
|
<option value="CRYPT">CRYPT — Kryptographie</option>
|
|
<option value="NET">NET — Netzwerk</option>
|
|
<option value="DATA">DATA — Datenschutz</option>
|
|
<option value="LOG">LOG — Logging</option>
|
|
<option value="ACC">ACC — Zugriffskontrolle</option>
|
|
<option value="SEC">SEC — Sicherheit</option>
|
|
<option value="INC">INC — Incident Response</option>
|
|
<option value="AI">AI — Kuenstliche Intelligenz</option>
|
|
<option value="COMP">COMP — Compliance</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-xs font-medium text-gray-600 mb-1">Max. Controls: {genMaxControls}</label>
|
|
<input
|
|
type="range" min="1" max="100" step="1"
|
|
value={genMaxControls}
|
|
onChange={e => setGenMaxControls(parseInt(e.target.value))}
|
|
className="w-full"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
id="dryRun"
|
|
checked={genDryRun}
|
|
onChange={e => setGenDryRun(e.target.checked)}
|
|
className="rounded border-gray-300"
|
|
/>
|
|
<label htmlFor="dryRun" className="text-sm text-gray-700">Dry Run (Vorschau ohne Speicherung)</label>
|
|
</div>
|
|
|
|
<button
|
|
onClick={onGenerate}
|
|
disabled={generating}
|
|
className="w-full py-2 text-sm text-white bg-amber-600 rounded-lg hover:bg-amber-700 disabled:opacity-50 flex items-center justify-center gap-2"
|
|
>
|
|
{generating ? (
|
|
<><RefreshCw className="w-4 h-4 animate-spin" /> Generiere...</>
|
|
) : (
|
|
<><Zap className="w-4 h-4" /> Generierung starten</>
|
|
)}
|
|
</button>
|
|
|
|
{/* Results */}
|
|
{genResult && (
|
|
<div className={`p-4 rounded-lg text-sm ${genResult.status === 'error' ? 'bg-red-50 text-red-800' : 'bg-green-50 text-green-800'}`}>
|
|
<p className="font-medium mb-1">{String(genResult.message || genResult.status)}</p>
|
|
{genResult.status !== 'error' && (
|
|
<div className="grid grid-cols-2 gap-1 text-xs mt-2">
|
|
<span>Chunks gescannt: {String(genResult.total_chunks_scanned)}</span>
|
|
<span>Controls generiert: {String(genResult.controls_generated)}</span>
|
|
<span>Verifiziert: {String(genResult.controls_verified)}</span>
|
|
<span>Review noetig: {String(genResult.controls_needs_review)}</span>
|
|
<span>Zu aehnlich: {String(genResult.controls_too_close)}</span>
|
|
<span>Duplikate: {String(genResult.controls_duplicates_found)}</span>
|
|
</div>
|
|
)}
|
|
{Array.isArray(genResult.errors) && (genResult.errors as string[]).length > 0 && (
|
|
<div className="mt-2 text-xs text-red-600">
|
|
{(genResult.errors as string[]).slice(0, 3).map((e, i) => <p key={i}>{e}</p>)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|