diff --git a/src/pages/home/HomeMap.tsx b/src/pages/home/HomeMap.tsx index c4ea97b..97cd2a8 100644 --- a/src/pages/home/HomeMap.tsx +++ b/src/pages/home/HomeMap.tsx @@ -1,15 +1,95 @@ "use client"; +import { useEffect, useState } from "react"; import WorldMap from "@/components/ui/world-map"; import { Eyebrow, H3, P } from "@/components/Texts"; -const stats = [ - { id: 1, name: 'CORES', value: '54,958', description: 'Total Central Processing Unit cores available on the grid.' }, - { id: 2, name: 'NODES', value: '1,493', description: 'Total number of nodes on the grid.' }, - { id: 3, name: 'SSD CAPACITY', value: '5,388,956', description: 'Total GB of storage (SSD, HDD, & RAM) on the grid.' }, - { id: 4, name: 'COUNTRIES', value: '44', description: 'Total number of countries with active nodes.' }, -] +type StatKey = "cores" | "nodes" | "ssd" | "countries"; + +type StatsData = Record; + +const STAT_API_URL = "https://stats.grid.tf/api/stats-summary"; + +const DEFAULT_STATS: StatsData = { + cores: "31,669", + nodes: "1157", + ssd: "4,199,303", + countries: "41", +}; + +const STAT_CARDS: Array<{ key: StatKey; title: string; description: string }> = [ + { + key: "ssd", + title: "SSD CAPACITY", + description: "Total GB of storage (SSD, HDD, & RAM) on the grid.", + }, + { + key: "cores", + title: "CORES", + description: "Total Central Processing Unit cores available on the grid.", + }, + { + key: "nodes", + title: "NODES", + description: "Total number of nodes on the grid.", + }, + + { + key: "countries", + title: "COUNTRIES", + description: "Total number of countries with active nodes.", + }, +]; export function HomeMap() { + const [stats, setStats] = useState(DEFAULT_STATS); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + let isMounted = true; + + const formatValue = (value: unknown, fallback: string) => { + if (typeof value === "number") { + return value.toLocaleString(); + } + if (typeof value === "string" && value.trim().length) { + const numeric = Number(value); + return Number.isNaN(numeric) ? value : numeric.toLocaleString(); + } + return fallback; + }; + + async function fetchStats() { + try { + const response = await fetch(STAT_API_URL); + if (!response.ok) { + throw new Error(`Request failed with ${response.status}`); + } + const data = await response.json(); + + if (!isMounted) return; + + setStats({ + cores: formatValue(data?.cores, DEFAULT_STATS.cores), + nodes: formatValue(data?.nodes, DEFAULT_STATS.nodes), + ssd: formatValue(data?.ssd, DEFAULT_STATS.ssd), + countries: formatValue(data?.countries, DEFAULT_STATS.countries), + }); + } catch (error) { + console.error("[HomeMap] Failed to load stats", error); + } finally { + if (isMounted) { + setIsLoading(false); + } + } + } + + fetchStats(); + + return () => { + isMounted = false; + }; + }, []); + return (
{/* ✅ Top horizontal line with spacing */} @@ -48,21 +128,21 @@ Configure it once. Your node takes over from there.
- {stats.map((stat) => ( + {STAT_CARDS.map(({ key, title, description }) => (
- {stat.name} + {title}
- {stat.value} + {isLoading ? "…" : stats[key]}

- {stat.description} + {description}

))}