website (17 pages + 3 components): - multiplayer/wizard, middleware/wizard+test-wizard, communication - builds/wizard, staff-search, voice, sbom/wizard - foerderantrag, mail/tasks, tools/communication, sbom - compliance/evidence, uni-crawler, brandbook (already done) - CollectionsTab, IngestionTab, RiskHeatmap backend-lehrer (5 files): - letters_api (641 → 2), certificates_api (636 → 2) - alerts_agent/db/models (636 → 3) - llm_gateway/communication_service (614 → 2) - game/database already done in prior batch klausur-service (2 files): - hybrid_vocab_extractor (664 → 2) - klausur-service/frontend: api.ts (620 → 3), EHUploadWizard (591 → 2) voice-service (3 files): - bqas/rag_judge (618 → 3), runner (529 → 2) - enhanced_task_orchestrator (519 → 2) studio-v2 (6 files): - korrektur/[klausurId] (578 → 4), fairness (569 → 2) - AlertsWizard (552 → 2), OnboardingWizard (513 → 2) - korrektur/api.ts (506 → 3), geo-lernwelt (501 → 2) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
'use client'
|
|
|
|
import { useMemo } from 'react'
|
|
import { Risk, RISK_LEVEL_COLORS, calculateRiskLevel } from './risk-heatmap-types'
|
|
|
|
interface MiniRiskMatrixProps {
|
|
risks: Risk[]
|
|
size?: 'sm' | 'md'
|
|
}
|
|
|
|
export function MiniRiskMatrix({ risks, size = 'sm' }: MiniRiskMatrixProps) {
|
|
const matrix = useMemo(() => {
|
|
const m: Record<number, Record<number, number>> = {}
|
|
for (let l = 1; l <= 5; l++) {
|
|
m[l] = {}
|
|
for (let i = 1; i <= 5; i++) {
|
|
m[l][i] = 0
|
|
}
|
|
}
|
|
risks.forEach((r) => {
|
|
if (m[r.likelihood] && m[r.likelihood][r.impact] !== undefined) {
|
|
m[r.likelihood][r.impact]++
|
|
}
|
|
})
|
|
return m
|
|
}, [risks])
|
|
|
|
const cellSize = size === 'sm' ? 'w-6 h-6' : 'w-8 h-8'
|
|
const fontSize = size === 'sm' ? 'text-[8px]' : 'text-[10px]'
|
|
|
|
return (
|
|
<div className="inline-block">
|
|
{[5, 4, 3, 2, 1].map((l) => (
|
|
<div key={l} className="flex">
|
|
{[1, 2, 3, 4, 5].map((i) => {
|
|
const level = calculateRiskLevel(l, i)
|
|
const count = matrix[l][i]
|
|
const colors = RISK_LEVEL_COLORS[level]
|
|
|
|
return (
|
|
<div
|
|
key={i}
|
|
className={`${cellSize} ${colors.bg} border ${colors.border} flex items-center justify-center m-px rounded-sm`}
|
|
>
|
|
{count > 0 && (
|
|
<span className={`${fontSize} font-bold ${colors.text}`}>{count}</span>
|
|
)}
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|