import { useState, useEffect, useCallback } from "react"; import { Link } from "react-router"; import type { MostActiveStock } from "../types"; function formatVolume(vol: number): string { if (vol >= 1_000_000_000) return `${(vol / 1_000_000_000).toFixed(1)}B`; if (vol >= 1_000_000) return `${(vol / 1_000_000).toFixed(1)}M`; if (vol >= 1_000) return `${(vol / 1_000).toFixed(1)}K`; return vol.toString(); } function formatPrice(price: number): string { return `$${price.toFixed(2)}`; } function formatChangePercent(pct: number): string { return `${pct >= 0 ? "+" : ""}${pct.toFixed(2)}%`; } export default function MostActiveStocks() { const [stocks, setStocks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setError(null); const res = await fetch("/api/stocks/most-actives"); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Failed to fetch data"); } const data = await res.json(); setStocks(data); } catch (err) { const message = err instanceof Error ? err.message : "Failed to fetch most active stocks."; setError(message); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); const interval = setInterval(fetchData, 30000); return () => clearInterval(interval); }, [fetchData]); if (loading) { return (
{Array.from({ length: 8 }).map((_, i) => (
))}
); } if (error && stocks.length === 0) { return (

{error}

); } return (
{error && (

{error}

)}
{stocks.map((stock) => ( ))}
Symbol Name Price Change % Volume
{stock.symbol} {stock.name} {formatPrice(stock.price)} = 0 ? "text-green-600" : "text-red-600"}`}> {formatChangePercent(stock.changePercent)} {formatVolume(stock.volume)}
); }