Whistleblower (1220 -> 349 LOC) split into 6 colocated components:
TabNavigation, StatCard, FilterBar, ReportCard, WhistleblowerCreateModal,
CaseDetailPanel. All under the 300 LOC soft target.
Drive-by fix: the earlier fc6a330 split of compliance-scope-types.ts
dropped several helper exports that downstream consumers still import
(lib/sdk/index.ts, compliance-scope-engine.ts, obligations page,
compliance-scope page, constraint-enforcer, drafting-engine validate).
Restored them in the appropriate domain modules:
- core-levels.ts: maxDepthLevel, getDepthLevelNumeric, depthLevelFromNumeric
- state.ts: createEmptyScopeState
- decisions.ts: createEmptyScopeDecision + ApplicableRegulation,
RegulationObligation, RegulationAssessmentResult, SupervisoryAuthorityInfo
Verification: next build clean (142 pages generated), /sdk/whistleblower
still builds at ~11.5 kB.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
'use client'
|
|
|
|
import React from 'react'
|
|
|
|
export function StatCard({
|
|
label,
|
|
value,
|
|
color = 'gray',
|
|
icon,
|
|
trend
|
|
}: {
|
|
label: string
|
|
value: number | string
|
|
color?: 'gray' | 'blue' | 'yellow' | 'red' | 'green' | 'purple'
|
|
icon?: React.ReactNode
|
|
trend?: { value: number; label: string }
|
|
}) {
|
|
const colorClasses = {
|
|
gray: 'border-gray-200 text-gray-900',
|
|
blue: 'border-blue-200 text-blue-600',
|
|
yellow: 'border-yellow-200 text-yellow-600',
|
|
red: 'border-red-200 text-red-600',
|
|
green: 'border-green-200 text-green-600',
|
|
purple: 'border-purple-200 text-purple-600'
|
|
}
|
|
|
|
return (
|
|
<div className={`bg-white rounded-xl border ${colorClasses[color]} p-6`}>
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<div className={`text-sm ${color === 'gray' ? 'text-gray-500' : `text-${color}-600`}`}>
|
|
{label}
|
|
</div>
|
|
<div className={`text-3xl font-bold mt-1 ${colorClasses[color].split(' ')[1]}`}>
|
|
{value}
|
|
</div>
|
|
{trend && (
|
|
<div className={`text-xs mt-1 ${trend.value >= 0 ? 'text-green-600' : 'text-red-600'}`}>
|
|
{trend.value >= 0 ? '+' : ''}{trend.value} {trend.label}
|
|
</div>
|
|
)}
|
|
</div>
|
|
{icon && (
|
|
<div className={`w-10 h-10 rounded-lg flex items-center justify-center bg-${color}-50`}>
|
|
{icon}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|