/ src / components / NetworkStats.tsx
NetworkStats.tsx
 1  'use client';
 2  
 3  import { useExplorerStore } from '@/store/explorer';
 4  import { formatNumber, formatCompact } from '@/lib/utils';
 5  import {
 6    Blocks,
 7    ArrowLeftRight,
 8    Users,
 9    Coins,
10  } from 'lucide-react';
11  
12  interface StatCardProps {
13    title: string;
14    value: string;
15    icon: React.ReactNode;
16    subtitle?: React.ReactNode;
17  }
18  
19  function StatCard({ title, value, icon, subtitle }: StatCardProps) {
20    return (
21      <div className="bg-card rounded-xl p-5 border border-border/50">
22        <div className="flex items-start justify-between">
23          <div>
24            <p className="text-gray-400 text-sm mb-1">{title}</p>
25            <p className="text-2xl font-bold text-white">{value}</p>
26            {subtitle && (
27              <p className="text-gray-500 text-xs mt-1">{subtitle}</p>
28            )}
29          </div>
30          <div className="text-accent p-2 bg-accent/10 rounded-lg">
31            {icon}
32          </div>
33        </div>
34      </div>
35    );
36  }
37  
38  export function NetworkStats() {
39    const { networkStats } = useExplorerStore();
40  
41    const healthColor =
42      networkStats.networkHealth === 'healthy'
43        ? 'text-success'
44        : networkStats.networkHealth === 'degraded'
45          ? 'text-warning'
46          : 'text-error';
47  
48    return (
49      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
50        <StatCard
51          title="Block Height"
52          value={formatNumber(networkStats.blockHeight)}
53          icon={<Blocks className="w-5 h-5" />}
54          subtitle={`${networkStats.averageBlockTime.toFixed(1)}s avg block time`}
55        />
56        <StatCard
57          title="Total Transactions"
58          value={formatCompact(networkStats.totalTransactions)}
59          icon={<ArrowLeftRight className="w-5 h-5" />}
60          subtitle={`${formatNumber(networkStats.tps)} TPS`}
61        />
62        <StatCard
63          title="Validators"
64          value={formatNumber(networkStats.validators)}
65          icon={<Users className="w-5 h-5" />}
66          subtitle="Active validators"
67        />
68        <StatCard
69          title="Total Staked"
70          value={`${formatCompact(parseFloat(networkStats.totalStaked))} AX`}
71          icon={<Coins className="w-5 h-5" />}
72          subtitle={
73            <span className={healthColor}>
74              Network {networkStats.networkHealth}
75            </span>
76          }
77        />
78      </div>
79    );
80  }
81  
82  export function NetworkHealthBadge() {
83    const { networkStats } = useExplorerStore();
84  
85    const statusConfig: Record<'healthy' | 'degraded' | 'down', { color: string; text: string }> = {
86      healthy: { color: 'bg-success', text: 'Healthy' },
87      degraded: { color: 'bg-warning', text: 'Degraded' },
88      down: { color: 'bg-error', text: 'Down' },
89    };
90  
91    const config = statusConfig[networkStats.networkHealth];
92  
93    return (
94      <div className="flex items-center gap-2">
95        <span className={`w-2 h-2 rounded-full ${config.color} animate-pulse`} />
96        <span className="text-sm text-gray-400">Network: {config.text}</span>
97      </div>
98    );
99  }