refactor(admin): split whistleblower page.tsx + restore scope helpers
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>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
'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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user