'use client'; import { NEXT_PUBLIC_HOME_LOCATION_COUNT, NEXT_PUBLIC_HOME_SERVER_COUNT, NEXT_PUBLIC_HOME_USER_COUNT, } from '@/config/constants'; import { DotLottieReact } from '@lottiefiles/dotlottie-react'; import LocationsLittie from '@workspace/ui/lotties/locations.json'; import ServersLottie from '@workspace/ui/lotties/servers.json'; import UsersLottie from '@workspace/ui/lotties/users.json'; import { motion } from 'framer-motion'; import { useTranslations } from 'next-intl'; import { useEffect, useState } from 'react'; export function Stats() { const t = useTranslations('index'); const list = [ { name: t('users'), number: NEXT_PUBLIC_HOME_USER_COUNT, icon: , }, { name: t('servers'), number: NEXT_PUBLIC_HOME_SERVER_COUNT, icon: , }, { name: t('locations'), number: NEXT_PUBLIC_HOME_LOCATION_COUNT, icon: , }, ]; return ( {list.map((item, index) => (
{item.icon}

+

{item.name}

))}
); } function CountUp({ end, duration = 2000 }: { end: number; duration?: number }) { const [count, setCount] = useState(0); useEffect(() => { let startTime: number; let animationFrame: number; const easeOutQuad = (t: number) => t * (2 - t); const updateCount = (timestamp: number) => { if (!startTime) startTime = timestamp; const progress = timestamp - startTime; const easedProgress = easeOutQuad(Math.min(progress / duration, 1)); const nextCount = Math.round(easedProgress * end); setCount(nextCount); if (progress < duration) { animationFrame = requestAnimationFrame(updateCount); } }; animationFrame = requestAnimationFrame(updateCount); return () => cancelAnimationFrame(animationFrame); }, [end, duration]); return <>{count.toLocaleString()}; }