'use client'; import { useEffect, useRef, useState } from 'react'; interface AnimatedCounterProps { end: number; duration?: number; prefix?: string; suffix?: string; decimals?: number; className?: string; } export default function AnimatedCounter({ end, duration = 2000, prefix = '', suffix = '', decimals = 0, className = '', }: AnimatedCounterProps) { const [count, setCount] = useState(0); const countRef = useRef(0); const startTimeRef = useRef(null); const frameRef = useRef(null); useEffect(() => { // Reset when end value changes countRef.current = 0; startTimeRef.current = null; setCount(0); const animate = (timestamp: number) => { if (startTimeRef.current === null) { startTimeRef.current = timestamp; } const progress = timestamp - startTimeRef.current; const percentage = Math.min(progress / duration, 1); // Easing function for smoother animation const easeOutQuart = 1 - Math.pow(1 - percentage, 4); const currentCount = Math.min(easeOutQuart * end, end); countRef.current = currentCount; setCount(currentCount); if (percentage < 1) { frameRef.current = requestAnimationFrame(animate); } }; frameRef.current = requestAnimationFrame(animate); return () => { if (frameRef.current !== null) { cancelAnimationFrame(frameRef.current); } }; }, [end, duration]); const formatNumber = (num: number) => { return num.toFixed(decimals); }; return ( {prefix} {formatNumber(count)} {suffix} ); }