"use client"; import { useEffect, useRef } from "react"; interface RiskDialProps { score: number; size?: number; } export default function RiskDial({ score, size = 200 }: RiskDialProps) { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const dpr = window.devicePixelRatio || 1; canvas.width = size * dpr; canvas.height = size * dpr; ctx.scale(dpr, dpr); const cx = size / 2; const cy = size / 2; const radius = size * 0.38; const startAngle = Math.PI * 0.75; // 135° const endAngle = Math.PI * 2.25; // 405° (full 270° arc) const valueAngle = startAngle + (endAngle - startAngle) * (score / 100); // Background track ctx.beginPath(); ctx.arc(cx, cy, radius, startAngle, endAngle); ctx.strokeStyle = "#2d3447"; ctx.lineWidth = 12; ctx.lineCap = "round"; ctx.stroke(); // Score color const getColor = (s: number) => { if (s >= 75) return "#3b82d4"; // sapphire — healthy if (s >= 50) return "#d97706"; // amber — warning return "#dc2626"; // crimson — critical }; // Score arc if (score > 0) { ctx.beginPath(); ctx.arc(cx, cy, radius, startAngle, valueAngle); ctx.strokeStyle = getColor(score); ctx.lineWidth = 12; ctx.lineCap = "round"; ctx.stroke(); // Glow ctx.beginPath(); ctx.arc(cx, cy, radius, startAngle, valueAngle); ctx.strokeStyle = getColor(score) + "40"; ctx.lineWidth = 20; ctx.lineCap = "round"; ctx.stroke(); } // Score number ctx.fillStyle = "#e2e8f0"; ctx.font = `bold ${size * 0.22}px system-ui, sans-serif`; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(Math.round(score).toString(), cx, cy - 4); // Label ctx.fillStyle = "#64748b"; ctx.font = `${size * 0.07}px system-ui, sans-serif`; ctx.fillText("/ 100", cx, cy + size * 0.14); }, [score, size]); return (

Cyber Health Score

); }