feat: Analyse-Module auf 100% Runde 2 — CREATE-Forms, Button-Handler, Persistenz
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 36s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 36s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
Requirements: ADD-Form + Details-Panel mit Controls/Status-Anzeige Controls: ADD-Form + Effectiveness-Persistenz via PUT Evidence: Anzeigen/Herunterladen-Buttons mit fileUrl + disabled-State Risks: RiskMatrix Cell-Click filtert Risiko-Liste mit Badge + Reset AI Act: Mock-Daten entfernt, Loading-Skeleton, Edit/Delete-Handler Audit Checklist: JSON-Export, debounced Notes-Persistenz, Neue Checkliste Audit Report: Animiertes Skeleton statt Loading-Text Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -387,6 +387,7 @@ export default function RisksPage() {
|
||||
const [editingRisk, setEditingRisk] = useState<Risk | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [matrixFilter, setMatrixFilter] = useState<{ likelihood: number; impact: number } | null>(null)
|
||||
|
||||
// Fetch risks from backend on mount
|
||||
useEffect(() => {
|
||||
@@ -595,14 +596,43 @@ export default function RisksPage() {
|
||||
{loading && <LoadingSkeleton />}
|
||||
|
||||
{/* Matrix */}
|
||||
{!loading && <RiskMatrix risks={state.risks} onCellClick={() => {}} />}
|
||||
{!loading && (
|
||||
<RiskMatrix
|
||||
risks={state.risks}
|
||||
onCellClick={(l, i) => {
|
||||
if (matrixFilter && matrixFilter.likelihood === l && matrixFilter.impact === i) {
|
||||
setMatrixFilter(null)
|
||||
} else {
|
||||
setMatrixFilter({ likelihood: l, impact: i })
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Matrix Filter Badge */}
|
||||
{matrixFilter && (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="px-3 py-1 text-sm bg-purple-100 text-purple-700 rounded-full flex items-center gap-2">
|
||||
Gefiltert: L={matrixFilter.likelihood} I={matrixFilter.impact}
|
||||
<button
|
||||
onClick={() => setMatrixFilter(null)}
|
||||
className="text-purple-500 hover:text-purple-700 font-bold"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Risk List */}
|
||||
{!loading && state.risks.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Alle Risiken</h3>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
||||
{matrixFilter ? `Risiken (L=${matrixFilter.likelihood}, I=${matrixFilter.impact})` : 'Alle Risiken'}
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
{state.risks
|
||||
.filter(risk => !matrixFilter || (risk.likelihood === matrixFilter.likelihood && risk.impact === matrixFilter.impact))
|
||||
.sort((a, b) => b.inherentRiskScore - a.inherentRiskScore)
|
||||
.map(risk => (
|
||||
<RiskCard
|
||||
|
||||
Reference in New Issue
Block a user