This repository has no description
1import React from 'react';
2import { PieChart, Pie, Cell } from 'recharts';
3
4const RADIAN = Math.PI / 180;
5const MAX_SCORE = 1000;
6
7const ScoreGauge = ({ score, shadowColor = 'rgba(150,127,0,0.74)' }) => {
8 const data = [
9 { name: 'Q1', value: 15, color: '#004F84' },
10 { name: 'Q2', value: 15, color: '#1368AA' },
11 { name: 'Q3', value: 40, color: '#2881D2' },
12 { name: 'Q4', value: 30, color: '#3B9AF8' },
13 ];
14
15 // Adjusted dimensions to match actual gauge size
16 const width = 300;
17 const height = 150;
18 const cx = width / 2;
19 const cy = height - 45; // Adjust center point to bottom half
20 const iR = 50;
21 const oR = 100;
22
23 const needle = (value, data, cx, cy, iR, oR, color) => {
24 const total = MAX_SCORE;
25 const ang = 180.0 * (1 - value / total);
26 const length = (iR + 2 * oR) / 2.5;
27 const sin = Math.sin(-RADIAN * ang);
28 const cos = Math.cos(-RADIAN * ang);
29 const r = 8;
30 const x0 = cx + 5;
31 const y0 = cy + 5;
32 const xba = x0 + r * sin;
33 const yba = y0 - r * cos;
34 const xbb = x0 - r * sin;
35 const ybb = y0 + r * cos;
36 const xp = x0 + length * cos;
37 const yp = y0 + length * sin;
38
39 return (
40 <g filter="url(#dropShadow)">
41 <path
42 d={`
43 M ${xba} ${yba}
44 L ${xbb} ${ybb}
45 L ${xp} ${yp}
46 L ${xba} ${yba}
47 Z
48 M ${x0} ${y0}
49 m -${r}, 0
50 a ${r},${r} 0 1,0 ${r*2},0
51 a ${r},${r} 0 1,0 -${r*2},0
52 `}
53 fill={color}
54 stroke="none"
55 pointerEvents="none"
56 tabIndex="-1"
57 aria-hidden="true"
58 />
59 </g>
60 );
61 };
62
63 return (
64 <div
65 className="score-gauge"
66 style={{
67 width: '100%',
68 maxWidth: '300px',
69 margin: '0 auto',
70 display: 'flex',
71 flexDirection: 'column',
72 alignItems: 'center'
73 }}
74 role="img"
75 aria-label={`Score gauge showing ${score} out of ${MAX_SCORE}`}
76 >
77 <PieChart
78 width={width}
79 height={height}
80 style={{ overflow: 'visible' }}
81 >
82 <defs>
83 <filter id="dropShadow">
84 <feDropShadow
85 dx="1"
86 dy="2"
87 stdDeviation="0"
88 floodColor={shadowColor}
89 floodOpacity="1"
90 />
91 </filter>
92 </defs>
93 <Pie
94 dataKey="value"
95 startAngle={180}
96 endAngle={0}
97 data={data}
98 cx={cx}
99 cy={cy}
100 innerRadius={iR}
101 outerRadius={oR}
102 fill="#8884d8"
103 stroke="none"
104 isAnimationActive={false}
105 >
106 {data.map((entry, index) => (
107 <Cell
108 key={`cell-${index}`}
109 fill={entry.color}
110 />
111 ))}
112 </Pie>
113 {needle(score, data, cx, cy, iR, oR, '#FFD700')}
114 </PieChart>
115 <div className="text-center font-semibold mt-2">
116 <strong>{score}</strong> <div className="max-score">/ {MAX_SCORE}</div>
117 </div>
118 </div>
119 );
120};
121
122export default ScoreGauge;