Spaces:
Sleeping
Sleeping
File size: 2,489 Bytes
a0da743 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 'use client';
interface ScoreRingProps {
score: number;
maxScore: number;
size?: number;
strokeWidth?: number;
label?: string;
showPercentage?: boolean;
color?: string;
}
export default function ScoreRing({
score,
maxScore,
size = 120,
strokeWidth = 8,
label,
showPercentage = true,
color,
}: ScoreRingProps) {
const radius = (size - strokeWidth) / 2;
const circumference = 2 * Math.PI * radius;
const percentage = Math.min((score / maxScore) * 100, 100);
const offset = circumference - (percentage / 100) * circumference;
const getColor = () => {
if (color) return color;
if (percentage >= 80) return 'var(--success)';
if (percentage >= 60) return 'var(--primary)';
if (percentage >= 40) return 'var(--warning)';
return 'var(--danger)';
};
const ringColor = getColor();
return (
<div className="flex flex-col items-center gap-2">
<div className="relative" style={{ width: size, height: size }}>
<svg
width={size}
height={size}
className="score-ring"
>
{/* Background circle */}
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke="var(--border)"
strokeWidth={strokeWidth}
/>
{/* Score circle */}
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke={ringColor}
strokeWidth={strokeWidth}
strokeLinecap="round"
strokeDasharray={circumference}
strokeDashoffset={offset}
style={{
filter: `drop-shadow(0 0 6px ${ringColor}40)`,
}}
/>
</svg>
{/* Center text */}
<div
className="absolute inset-0 flex flex-col items-center justify-center"
>
<span
className="font-bold"
style={{ fontSize: size * 0.22, color: ringColor }}
>
{showPercentage ? `${Math.round(percentage)}%` : score.toFixed(1)}
</span>
{!showPercentage && (
<span className="text-xs" style={{ color: 'var(--muted)' }}>
/ {maxScore}
</span>
)}
</div>
</div>
{label && (
<span className="text-sm font-medium" style={{ color: 'var(--muted-light)' }}>
{label}
</span>
)}
</div>
);
}
|