forked from emre/www_projectmycelium_com
update statics to be dynamic
This commit is contained in:
@@ -1,15 +1,95 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import WorldMap from "@/components/ui/world-map";
|
import WorldMap from "@/components/ui/world-map";
|
||||||
import { Eyebrow, H3, P } from "@/components/Texts";
|
import { Eyebrow, H3, P } from "@/components/Texts";
|
||||||
|
|
||||||
const stats = [
|
type StatKey = "cores" | "nodes" | "ssd" | "countries";
|
||||||
{ 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.' },
|
type StatsData = Record<StatKey, string>;
|
||||||
{ 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.' },
|
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() {
|
export function HomeMap() {
|
||||||
|
const [stats, setStats] = useState<StatsData>(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 (
|
return (
|
||||||
<div className="bg-[#121212] w-full">
|
<div className="bg-[#121212] w-full">
|
||||||
{/* ✅ Top horizontal line with spacing */}
|
{/* ✅ Top horizontal line with spacing */}
|
||||||
@@ -48,21 +128,21 @@ Configure it once. Your node takes over from there.
|
|||||||
<div className="mx-auto max-w-7xl px-6 lg:px-8 border border-t-0 border-b-0 border-gray-800 pb-12">
|
<div className="mx-auto max-w-7xl px-6 lg:px-8 border border-t-0 border-b-0 border-gray-800 pb-12">
|
||||||
|
|
||||||
<dl className="pt-6 grid grid-cols-1 gap-0.5 overflow-hidden rounded-md text-center sm:grid-cols-2 lg:grid-cols-4">
|
<dl className="pt-6 grid grid-cols-1 gap-0.5 overflow-hidden rounded-md text-center sm:grid-cols-2 lg:grid-cols-4">
|
||||||
{stats.map((stat) => (
|
{STAT_CARDS.map(({ key, title, description }) => (
|
||||||
<div
|
<div
|
||||||
key={stat.id}
|
key={key}
|
||||||
className="flex flex-col bg-white/1 p-8"
|
className="flex flex-col bg-white/1 p-8"
|
||||||
>
|
>
|
||||||
<dt className="text-sm/6 font-semibold text-gray-300">
|
<dt className="text-sm/6 font-semibold text-gray-300">
|
||||||
{stat.name}
|
{title}
|
||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
<dd className="order-first text-3xl font-semibold tracking-tight text-white">
|
<dd className="order-first text-3xl font-semibold tracking-tight text-white">
|
||||||
{stat.value}
|
{isLoading ? "…" : stats[key]}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<p className="mt-2 text-sm text-gray-400">
|
<p className="mt-2 text-sm text-gray-400">
|
||||||
{stat.description}
|
{description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user