Untitled
unknown
plain_text
10 months ago
3.9 kB
6
Indexable
'use client'
import { useEffect, useState } from 'react'
import { useTheme } from 'next-themes'
import { Label, PolarGrid, PolarRadiusAxis, RadialBar, RadialBarChart } from "recharts"
import { Card, CardContent } from "@/components/ui/card"
import { ChartContainer, ChartConfig } from "@/components/ui/chart"
import { cn } from "@/lib/utils"
interface CircularProgressProps {
binId: string
fillLevel: number
color: string
darkColor: string
name: string
}
export function CircularProgress({ binId, fillLevel, color, darkColor, name }: CircularProgressProps) {
const { theme } = useTheme()
const [progress, setProgress] = useState(0)
useEffect(() => {
const timer = setTimeout(() => setProgress(fillLevel), 100)
return () => clearTimeout(timer)
}, [fillLevel])
const isDarkMode = theme === 'dark'
const bgColor = isDarkMode ? darkColor : color
const textColor = getTextColor(bgColor)
const progressColor = getProgressColor(fillLevel, isDarkMode)
const chartConfig: ChartConfig = {
[binId]: {
label: name,
color: progressColor,
},
}
const chartData = [
{ name: `${binId}-progress`, value: progress, fill: progressColor }
]
return (
<Card className="w-full border-0 bg-transparent shadow-none">
<CardContent className="relative p-1">
<ChartContainer config={chartConfig} className="mx-auto aspect-square h-[400px]">
<svg
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
width="20%"
height="20%"
viewBox="0 0 100 100"
>
<circle
cx="52"
cy="50"
r="31"
fill={bgColor}
className={cn(
isDarkMode ? "opacity-[0.15]" : "opacity-[0.35]"
)}
/>
</svg>
<RadialBarChart
data={chartData}
startAngle={90}
endAngle={90 - (progress * 3.6)}
innerRadius="65%"
outerRadius="95%"
barSize={12}
>
<PolarRadiusAxis
tick={false}
axisLine={false}
tickLine={false}
stroke="none"
>
<Label
content={({ viewBox }) => {
if (viewBox && "cx" in viewBox && "cy" in viewBox) {
return (
<text
x={viewBox.cx}
y={viewBox.cy}
textAnchor="middle"
dominantBaseline="middle"
className="fill-foreground text-2xl font-medium"
>
{name}
</text>
)
}
}}
/>
</PolarRadiusAxis>
<RadialBar
background={false}
dataKey="value"
cornerRadius={15}
className="stroke-none"
/>
</RadialBarChart>
</ChartContainer>
</CardContent>
</Card>
)
}
function getProgressColor(level: number, isDark: boolean) {
if (isDark) {
if (level >= 80) return '#ff3b30'
if (level >= 60) return '#ff9f0a'
if (level >= 40) return '#ffd60a'
return '#30d158'
} else {
if (level >= 80) return '#ff453a'
if (level >= 60) return '#ff9f0a'
if (level >= 40) return '#ffd60a'
return '#34c759'
}
}
function getTextColor(backgroundColor: string) {
const rgb = parseInt(backgroundColor.slice(1), 16)
const r = (rgb >> 16) & 0xff
const g = (rgb >> 8) & 0xff
const b = (rgb >> 0) & 0xff
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
return luminance > 0.5 ? '#000000' : '#ffffff'
}
Editor is loading...
Leave a Comment