// Stats V2 — Counters that tick up when in view + animated rings const { useState: useStateStV2, useEffect: useEffectStV2, useRef: useRefStV2 } = React; const STATS_V2_DATA = [ { num: 60, suffix: "%", label: "Comenzi confirmate", caption: "din drafts" }, { num: 85, suffix: "%", label: "Comenzi confirmate", caption: "de Echipa Confirmări.ro" }, { num: 40, suffix: "s", label: "Timp mediu apel", caption: "de la sunet la confirmare" }, { num: 1.40, suffix: " RON",label: "Cost mediu/confirmare", caption: "raportat la 100 de comenzi reale", decimals: 2 }, ]; const useCountUp = (target, dur = 1400, start = false) => { const [v, setV] = useStateStV2(0); useEffectStV2(() => { if (!start) return; let raf, t0; const step = (now) => { if (!t0) t0 = now; const p = Math.min(1, (now - t0) / dur); setV(target * (1 - Math.pow(1 - p, 3))); // easeOut cubic if (p < 1) raf = requestAnimationFrame(step); }; raf = requestAnimationFrame(step); return () => cancelAnimationFrame(raf); }, [start, target, dur]); return v; }; const StatBlock = ({ s, idx, started, isMobile }) => { const v = useCountUp(s.num, 1600 + idx * 200, started); const display = s.decimals ? v.toFixed(s.decimals).replace(".", ",") + s.suffix : s.suffix === "/7" ? Math.round(v) + "/7" : Math.round(v) + s.suffix; return (
{display}
{s.label}
{s.caption}
{/* animated underline */}
); }; const StatsV2 = () => { const ref = useRefStV2(null); const [started, setStarted] = useStateStV2(false); const [isMobile, setIsMobile] = useStateStV2(false); useEffectStV2(() => { const check = () => setIsMobile(window.innerWidth < 760); check(); window.addEventListener("resize", check); return () => window.removeEventListener("resize", check); }, []); // Trigger count-up only when the stats grid scrolls into view useEffectStV2(() => { if (!ref.current) return; const io = new IntersectionObserver((entries) => { for (const e of entries) { if (e.isIntersecting) { setStarted(true); io.disconnect(); break; } } }, { threshold: 0.35, rootMargin: "0px 0px -10% 0px" }); io.observe(ref.current); return () => io.disconnect(); }, []); return (
{STATS_V2_DATA.map((s, i) => )}
); }; window.StatsV2 = StatsV2;