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 }