refactor(admin): split evidence, import, portfolio pages
Extract components and hooks from oversized pages into colocated _components/ and _hooks/ subdirectories to enforce the 500-LOC hard cap. page.tsx files reduced to 205, 121, and 136 LOC respectively. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
87
admin-compliance/app/sdk/risks/_components/RiskMatrix.tsx
Normal file
87
admin-compliance/app/sdk/risks/_components/RiskMatrix.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import { Risk } from '@/lib/sdk'
|
||||
|
||||
export function RiskMatrix({ risks, onCellClick }: { risks: Risk[]; onCellClick: (l: number, i: number) => void }) {
|
||||
const matrix: Record<string, Risk[]> = {}
|
||||
|
||||
risks.forEach(risk => {
|
||||
const key = `${risk.likelihood}-${risk.impact}`
|
||||
if (!matrix[key]) matrix[key] = []
|
||||
matrix[key].push(risk)
|
||||
})
|
||||
|
||||
const getCellColor = (likelihood: number, impact: number): string => {
|
||||
const score = likelihood * impact
|
||||
if (score >= 20) return 'bg-red-500'
|
||||
if (score >= 15) return 'bg-red-400'
|
||||
if (score >= 12) return 'bg-orange-400'
|
||||
if (score >= 8) return 'bg-yellow-400'
|
||||
if (score >= 4) return 'bg-yellow-300'
|
||||
return 'bg-green-400'
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">5x5 Risikomatrix</h3>
|
||||
<div className="flex">
|
||||
<div className="flex flex-col justify-center pr-2">
|
||||
<div className="transform -rotate-90 whitespace-nowrap text-sm text-gray-500 font-medium">
|
||||
Wahrscheinlichkeit
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<div className="grid grid-cols-5 gap-1">
|
||||
{[5, 4, 3, 2, 1].map(likelihood => (
|
||||
<React.Fragment key={likelihood}>
|
||||
{[1, 2, 3, 4, 5].map(impact => {
|
||||
const key = `${likelihood}-${impact}`
|
||||
const cellRisks = matrix[key] || []
|
||||
return (
|
||||
<button
|
||||
key={key}
|
||||
onClick={() => onCellClick(likelihood, impact)}
|
||||
className={`aspect-square rounded-lg ${getCellColor(
|
||||
likelihood,
|
||||
impact
|
||||
)} hover:opacity-80 transition-opacity relative`}
|
||||
>
|
||||
{cellRisks.length > 0 && (
|
||||
<span className="absolute inset-0 flex items-center justify-center text-white font-bold text-lg">
|
||||
{cellRisks.length}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-2 text-center text-sm text-gray-500 font-medium">Auswirkung</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex items-center justify-center gap-4 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 rounded bg-green-400" />
|
||||
<span>Niedrig</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 rounded bg-yellow-400" />
|
||||
<span>Mittel</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 rounded bg-orange-400" />
|
||||
<span>Hoch</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 rounded bg-red-500" />
|
||||
<span>Kritisch</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user