11import React from 'react'
2- import { Label , Pie , PieChart } from 'recharts'
32import { cn } from '@/lib/utils'
4- import { ChartContainer } from '@/components/ui/chart'
5- import { ScoreCardCheck } from './types'
63
74interface OverallScoreGaugeProps {
85 score : number
96 maxScore ?: number
10- checks ?: ScoreCardCheck [ ]
117}
128
139function getScoreLabel ( score : number ) : string {
@@ -18,130 +14,36 @@ function getScoreLabel(score: number): string {
1814 return 'Critical'
1915}
2016
21- function getScoreLabelColor ( score : number ) : string {
22- if ( score >= 7 ) return 'text-green-400'
23- if ( score >= 4 ) return 'text-yellow-400'
24- return 'text-red-400'
25- }
26-
27- function getScoreFill ( score : number ) : string {
28- if ( score >= 7 ) return '#4ade80'
29- if ( score >= 4 ) return '#facc15'
30- return '#f87171'
17+ function getScoreBadgeClasses ( score : number ) : string {
18+ if ( score >= 8 ) return 'bg-green-400/15 text-green-400 border-green-400/30'
19+ if ( score >= 6 ) return 'bg-green-400/10 text-green-300 border-green-300/30'
20+ if ( score >= 4 ) return 'bg-yellow-400/15 text-yellow-400 border-yellow-400/30'
21+ if ( score >= 2 ) return 'bg-orange-400/15 text-orange-400 border-orange-400/30'
22+ return 'bg-red-400/15 text-red-400 border-red-400/30'
3123}
3224
3325export default function OverallScoreGauge ( {
3426 score,
3527 maxScore = 10 ,
36- checks,
3728} : OverallScoreGaugeProps ) {
38- const passingCount = checks ?. filter ( ( c ) => c . score > 0 ) . length ?? 0
39- const failingCount = checks ?. filter ( ( c ) => c . score === 0 ) . length ?? 0
40- const naCount = checks ?. filter ( ( c ) => c . score < 0 ) . length ?? 0
41- const data = [
42- {
43- name : 'Score' ,
44- value : score ,
45- fill : getScoreFill ( score ) ,
46- } ,
47- {
48- name : 'Remaining' ,
49- value : maxScore - score ,
50- fill : 'hsl(var(--secondary))' ,
51- } ,
52- ]
53-
5429 return (
55- < div className = "flex items-center" >
56- < div className = "flex flex-col items-center pr-5" >
57- < h3 className = "mb-2 text-base font-semibold text-white" >
58- Overall Score
59- </ h3 >
60- < div className = "h-[154px] w-[170px]" >
61- < ChartContainer config = { { } } className = "aspect-square w-full" >
62- < PieChart >
63- < Pie
64- data = { data }
65- startAngle = { - 270 }
66- dataKey = "value"
67- nameKey = "name"
68- innerRadius = { 42 }
69- strokeWidth = { 2 }
70- >
71- < Label
72- content = { ( { viewBox } ) => {
73- if (
74- viewBox &&
75- 'cx' in viewBox &&
76- 'cy' in viewBox
77- ) {
78- return (
79- < text
80- x = { viewBox . cx }
81- y = { viewBox . cy }
82- textAnchor = "middle"
83- dominantBaseline = "middle"
84- >
85- < tspan
86- x = { viewBox . cx }
87- y = { viewBox . cy }
88- className = "fill-foreground text-3xl font-bold"
89- >
90- { score . toFixed ( 1 ) }
91- </ tspan >
92- < tspan
93- x = { viewBox . cx }
94- y = { ( viewBox . cy || 0 ) + 19 }
95- className = "fill-muted-foreground text-sm"
96- >
97- / { maxScore }
98- </ tspan >
99- </ text >
100- )
101- }
102- } }
103- />
104- </ Pie >
105- </ PieChart >
106- </ ChartContainer >
107- </ div >
30+ < div className = "flex items-center gap-3" >
31+ < span className = "text-sm text-gray-400" > Overall Score</ span >
32+ < span className = "font-mono text-lg font-bold text-white" >
33+ { score . toFixed ( 1 ) }
34+ < span className = "text-sm font-normal text-gray-500" >
35+ { ' ' }
36+ / { maxScore }
37+ </ span >
38+ </ span >
10839 < span
10940 className = { cn (
110- 'mt-2 text-base font-semibold' ,
111- getScoreLabelColor ( score ) ,
41+ 'rounded-full border px-2.5 py-0.5 text-xs font-semibold' ,
42+ getScoreBadgeClasses ( score ) ,
11243 ) }
11344 >
11445 { getScoreLabel ( score ) }
11546 </ span >
116- </ div >
117- { checks && (
118- < div className = "mt-3 flex flex-col items-center gap-3" >
119- < div className = "text-center" >
120- < div className = "font-mono text-base font-bold text-green-400" >
121- { passingCount }
122- </ div >
123- < div className = "text-[10px] text-gray-500" >
124- passing
125- </ div >
126- </ div >
127- < div className = "w-full h-px bg-white/[0.06]" />
128- < div className = "text-center" >
129- < div className = "font-mono text-base font-bold text-red-400" >
130- { failingCount }
131- </ div >
132- < div className = "text-[10px] text-gray-500" >
133- failing
134- </ div >
135- </ div >
136- < div className = "w-full h-px bg-white/[0.06]" />
137- < div className = "text-center" >
138- < div className = "font-mono text-base font-bold text-gray-500" >
139- { naCount }
140- </ div >
141- < div className = "text-[10px] text-gray-500" > n/a</ div >
142- </ div >
143- </ div >
144- ) }
14547 </ div >
14648 )
14749}
0 commit comments