Extract types, constants, helpers, and UI pieces (LoadingSkeleton, EmptyState, StatCard, ComplianceRing, Modal, TenantCard, CreateTenantModal, EditTenantModal, TenantDetailModal) into _components/ and _types.ts to bring page.tsx from 1663 LOC to 432 LOC (under the 500 hard cap). Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
'use client'
|
|
|
|
import { getScoreColor } from './helpers'
|
|
|
|
export function ComplianceRing({ score, size = 64 }: { score: number; size?: number }) {
|
|
const strokeWidth = 5
|
|
const radius = (size - strokeWidth) / 2
|
|
const circumference = 2 * Math.PI * radius
|
|
const progress = Math.max(0, Math.min(100, score))
|
|
const offset = circumference - (progress / 100) * circumference
|
|
const color = getScoreColor(score)
|
|
|
|
return (
|
|
<div className="relative" style={{ width: size, height: size }}>
|
|
<svg width={size} height={size} className="transform -rotate-90">
|
|
<circle
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
fill="none"
|
|
stroke="#e2e8f0"
|
|
strokeWidth={strokeWidth}
|
|
/>
|
|
<circle
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
fill="none"
|
|
stroke={color}
|
|
strokeWidth={strokeWidth}
|
|
strokeDasharray={circumference}
|
|
strokeDashoffset={offset}
|
|
strokeLinecap="round"
|
|
className="transition-all duration-700 ease-out"
|
|
/>
|
|
</svg>
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<span className="text-sm font-bold text-slate-900">{score}</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|