Metric.tsx
1 import { useInMobile } from "../hooks/useInMobile"; 2 import { useEffect, useState } from "react"; 3 import { MetricCard, MetricCardSkeleton } from "../ZcashMetrics/MetricCard"; 4 5 // interface CoinData { 6 // usd?: number; 7 // btc?: number; 8 // usd_market_cap?: number; 9 // usd_24h_vol?: number; 10 // usd_24h_change?: number; 11 // } 12 13 interface BlockchainInfo { 14 market_cap_usd: number; 15 market_price_usd: number; 16 market_price_btc: number; 17 blocks: number; 18 transactions_24h: number; 19 } 20 21 const CryptoMetrics = ({ selectedCoin }: { selectedCoin: string }) => { 22 // const [coinData, setCoinData] = useState<CoinData | null>(null); 23 const [blockchainInfo, setBlockchainInfo] = useState<BlockchainInfo | null>({ 24 market_cap_usd: 0, 25 market_price_usd: 0, 26 market_price_btc: 0, 27 blocks: Math.floor(Math.random() * 2000000), 28 transactions_24h: 0, 29 }); 30 const [circulation, setCirculation] = useState<number | null>(null); 31 const [loading, setLoading] = useState(true); 32 const [error, setError] = useState<string | null>(null); 33 const isMobile = useInMobile(); 34 35 useEffect(() => { 36 let name = selectedCoin; 37 const fetchCoinData = async () => { 38 // Skip fetch for Namada and Zcash (or handle differently) 39 if (selectedCoin === "Zcash") { 40 setLoading(false); 41 return; 42 } 43 44 if (selectedCoin === "Atom") { 45 name = "Cosmos Hub"; 46 } else if (selectedCoin === "Tia") { 47 name = "Celestia"; 48 } else if (selectedCoin === "Osmo") { 49 name = "Osmosis"; 50 } else if (selectedCoin === "stOsmo") { 51 name = "Stride Staked Osmo"; 52 } else if (selectedCoin === "stTia") { 53 name = "Stride Staked TIA"; 54 } else if (selectedCoin === "stAtom") { 55 name = "Stride Staked Atom"; 56 } else if (selectedCoin === "Um") { 57 name = "Penumbra"; 58 } else if (selectedCoin === "Ntrn") { 59 name = "Neutron"; 60 } 61 62 try { 63 setLoading(true); 64 setError(null); 65 66 // Fetch CoinGecko data 67 const options = { 68 method: "GET", 69 headers: { 70 accept: "application/json", 71 "x-cg-demo-api-key": "CG-C7uDKWaJaNy8ZTtVb6bWv19d", 72 }, 73 }; 74 75 const response = await fetch( 76 `https://api.coingecko.com/api/v3/simple/price?vs_currencies=usd%2Cbtc&names=${encodeURIComponent( 77 name.toLowerCase() 78 )}&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true`, 79 options 80 ); 81 82 if (!response.ok) { 83 throw new Error(`Failed to fetch data: ${response.status}`); 84 } 85 86 const data = await response.json(); 87 88 if (name == "Usdc") { 89 name = "USDC"; 90 } 91 const coinInfo = data[name]; 92 // setCoinData(coinInfo); 93 94 // Mock blockchain data (replace with actual API calls) 95 setBlockchainInfo({ 96 market_cap_usd: coinInfo?.usd_market_cap || 0, 97 market_price_usd: coinInfo?.usd || 0, 98 market_price_btc: coinInfo?.btc || 0, 99 blocks: Math.floor(Math.random() * 2000000), 100 transactions_24h: coinInfo?.usd_24h_vol || 0, 101 }); 102 103 setCirculation( 104 Math.floor( 105 coinInfo?.usd_market_cap 106 ? coinInfo?.usd_market_cap / coinInfo?.usd 107 : 0 108 ) 109 ); 110 } catch (err) { 111 console.error("Failed to fetch coin data:", err); 112 setError(err instanceof Error ? err.message : "Unknown error occurred"); 113 } finally { 114 setLoading(false); 115 } 116 }; 117 118 fetchCoinData(); 119 }, [selectedCoin]); 120 121 const metricsObj = [ 122 { 123 label: "Market Cap", 124 value: blockchainInfo?.market_cap_usd 125 ? `$${blockchainInfo?.market_cap_usd.toLocaleString()}` 126 : "N/A", 127 }, 128 { 129 label: "Circulation", 130 value: circulation 131 ? `${circulation?.toLocaleString()} ${selectedCoin}` 132 : "N/A", 133 }, 134 { 135 label: "Market Price (USD)", 136 value: blockchainInfo?.market_price_usd 137 ? `$${blockchainInfo?.market_price_usd.toFixed(2)}` 138 : "N/A", 139 }, 140 { 141 label: "Market Price (BTC)", 142 value: blockchainInfo?.market_price_btc 143 ? isMobile 144 ? Number(blockchainInfo?.market_price_btc).toFixed(4) 145 : Number(blockchainInfo?.market_price_btc).toFixed(8) 146 : "N/A", 147 }, 148 { 149 label: "Blocks", 150 value: blockchainInfo?.blocks 151 ? blockchainInfo?.blocks.toLocaleString() 152 : "N/A", 153 }, 154 { 155 label: "24h Transactions", 156 value: Number(blockchainInfo?.transactions_24h) 157 ? blockchainInfo?.transactions_24h.toLocaleString() 158 : "N/A", 159 }, 160 ]; 161 162 return ( 163 <div className="my-12"> 164 <h2 className="font-bold text-xl text-slate-700 dark:text-slate-100"> 165 {loading ? ( 166 <div className="h-7 bg-gray-200 dark:bg-slate-700 rounded w-24 mb-2" /> 167 ) : ( 168 `${selectedCoin} Metrics` 169 )} 170 </h2> 171 172 <div className="grid grid-cols-1 imd:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 mt-8"> 173 {loading 174 ? metricsObj.map(({ label, value }) => ( 175 <MetricCardSkeleton key={label} /> 176 )) 177 : metricsObj.map(({ label, value }) => ( 178 <MetricCard label={label} value={value!} key={label} /> 179 ))} 180 </div> 181 {error && ( 182 <p className="flex items-center bg-red-300 text-red-400 mt-8 p-4"> 183 Error loading {selectedCoin} chart. 184 </p> 185 )} 186 </div> 187 ); 188 }; 189 190 export default CryptoMetrics;