72 lines
2.9 KiB
TypeScript
72 lines
2.9 KiB
TypeScript
import { motion } from 'framer-motion';
|
|
import { cn, formatAmount } from '@/lib/utils';
|
|
import { DirhamIcon } from '@/components/ui/custom-icons';
|
|
import React from 'react';
|
|
|
|
interface BudgetRingProps {
|
|
spent: number;
|
|
total: number;
|
|
label: string;
|
|
color?: string;
|
|
size?: 'sm' | 'md' | 'lg';
|
|
}
|
|
|
|
export const BudgetRing = ({ spent, total, label, color = "text-primary", size = "md" }: BudgetRingProps) => {
|
|
const percentage = Math.min(100, Math.max(0, (spent / total) * 100));
|
|
const radius = size === 'sm' ? 20 : size === 'md' ? 30 : 40;
|
|
const strokeWidth = size === 'sm' ? 4 : size === 'md' ? 6 : 8;
|
|
const circumference = 2 * Math.PI * radius;
|
|
const strokeDashoffset = circumference - (percentage / 100) * circumference;
|
|
|
|
return (
|
|
<div className="flex flex-col items-center justify-center p-4">
|
|
<div className="relative flex items-center justify-center">
|
|
{/* Background Circle */}
|
|
<svg className="transform -rotate-90 w-24 h-24">
|
|
<circle
|
|
cx="48"
|
|
cy="48"
|
|
r={radius}
|
|
stroke="currentColor"
|
|
strokeWidth={strokeWidth}
|
|
fill="transparent"
|
|
className="text-slate-100"
|
|
/>
|
|
{/* Progress Circle */}
|
|
<motion.circle
|
|
initial={{ strokeDashoffset: circumference }}
|
|
animate={{ strokeDashoffset }}
|
|
transition={{ duration: 1.5, ease: "easeOut" }}
|
|
cx="48"
|
|
cy="48"
|
|
r={radius}
|
|
stroke="currentColor"
|
|
strokeWidth={strokeWidth}
|
|
fill="transparent"
|
|
strokeDasharray={circumference}
|
|
strokeLinecap="round"
|
|
className={cn(color)}
|
|
/>
|
|
</svg>
|
|
<div className="absolute text-center">
|
|
<span className="text-xs font-bold text-slate-700">{Math.round(percentage)}%</span>
|
|
</div>
|
|
</div>
|
|
<div className="mt-2 text-center">
|
|
<p className="text-sm font-semibold text-slate-700">{label}</p>
|
|
<div className="flex items-center justify-center gap-1 text-xs text-slate-400">
|
|
<div className="flex items-center gap-0.5">
|
|
<DirhamIcon className="w-3 h-3" />
|
|
{formatAmount(spent)}
|
|
</div>
|
|
<span>/</span>
|
|
<div className="flex items-center gap-0.5">
|
|
<DirhamIcon className="w-3 h-3" />
|
|
{formatAmount(total)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|