Break 839-line page.tsx into _types.ts, _components/SourcesTab.tsx, JobsTab.tsx, DocumentsTab.tsx, ReportTab.tsx, and ComplianceRing.tsx. page.tsx is now 56 LOC (wiring only). No behavior changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
29 lines
1.0 KiB
TypeScript
29 lines
1.0 KiB
TypeScript
'use client'
|
|
|
|
export function ComplianceRing({ score }: { score: number }) {
|
|
const radius = 50
|
|
const circumference = 2 * Math.PI * radius
|
|
const offset = circumference - (score / 100) * circumference
|
|
const color = score >= 75 ? '#16a34a' : score >= 50 ? '#f59e0b' : '#dc2626'
|
|
|
|
return (
|
|
<div className="relative w-36 h-36">
|
|
<svg className="w-full h-full -rotate-90">
|
|
<circle cx="68" cy="68" r={radius} fill="none" stroke="#e5e7eb" strokeWidth="8" />
|
|
<circle
|
|
cx="68" cy="68" r={radius} fill="none"
|
|
stroke={color} strokeWidth="8"
|
|
strokeDasharray={circumference}
|
|
strokeDashoffset={offset}
|
|
strokeLinecap="round"
|
|
className="transition-all duration-1000"
|
|
/>
|
|
</svg>
|
|
<div className="absolute inset-0 flex flex-col items-center justify-center">
|
|
<span className="text-3xl font-bold" style={{ color }}>{score.toFixed(0)}%</span>
|
|
<span className="text-xs text-gray-500">Compliance</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|