Files
shimmer-finance-ai-companion/src/components/BudgetRing.tsx

72 lines
2.9 KiB
TypeScript
Raw Normal View History

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>
);
};