/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: client/src/components/explore/market-overview.tsx * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Website: https://www.spboucher.ai * Demo: https://www.vquant.ai * License: MIT (see LICENSE) * * Copyright © 2026 Simon-Pierre Boucher. All rights reserved. * ============================================================================= */ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { TrendingUp, TrendingDown, Activity, Clock, DollarSign, BarChart3 } from "lucide-react"; interface MarketIndex { symbol: string; name: string; price: number; change: number; changesPercentage: number; dayLow: number; dayHigh: number; yearHigh: number; yearLow: number; volume: number; previousClose: number; } interface MarketStatus { isTheStockMarketOpen: boolean; stockMarketHours: { openingHour: string; closingHour: string; }; } interface Stock { symbol: string; name: string; price: number; changesPercentage: number; change: number; volume?: number; marketCap?: number; } interface MarketOverviewProps { marketIndices?: MarketIndex[]; marketStatus?: MarketStatus; gainers?: Stock[]; losers?: Stock[]; activeStocks?: Stock[]; onTickerClick: (ticker: string) => void; } export function MarketOverview({ marketIndices, marketStatus, gainers, losers, activeStocks, onTickerClick }: MarketOverviewProps) { const formatNumber = (num: number) => { if (num >= 1e9) return `$${(num / 1e9).toFixed(2)}B`; if (num >= 1e6) return `$${(num / 1e6).toFixed(2)}M`; if (num >= 1e3) return `$${(num / 1e3).toFixed(2)}K`; return `$${num.toFixed(2)}`; }; const formatVolume = (vol: number) => { if (vol >= 1e9) return `${(vol / 1e9).toFixed(2)}B`; if (vol >= 1e6) return `${(vol / 1e6).toFixed(2)}M`; if (vol >= 1e3) return `${(vol / 1e3).toFixed(2)}K`; return vol.toString(); }; return (
{/* Market Status Banner */} {marketStatus && (
Statut du Marché Heures d'ouverture: {marketStatus.stockMarketHours?.openingHour} - {marketStatus.stockMarketHours?.closingHour}
{marketStatus.isTheStockMarketOpen ? "🟢 OUVERT" : "🔴 FERMÉ"}
)} {/* Major Indices */}

Indices Majeurs

Performance en temps réel des principaux indices boursiers

{marketIndices?.map((index) => { const isPositive = index.changesPercentage >= 0; return ( onTickerClick(index.symbol)} >
{index.name} {index.symbol}
{isPositive ? ( ) : ( )}
{index.price?.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
{isPositive ? '+' : ''}{index.change?.toFixed(2)} ({isPositive ? '+' : ''}{index.changesPercentage?.toFixed(2)}%)
Jour Bas/Haut
{index.dayLow > 0 ? `${index.dayLow.toFixed(2)} / ${index.dayHigh.toFixed(2)}` : 'N/A'}
Année Bas/Haut
{index.yearLow > 0 ? `${index.yearLow.toFixed(2)} / ${index.yearHigh.toFixed(2)}` : 'N/A'}
Clôture Précédente
{index.previousClose > 0 ? index.previousClose.toFixed(2) : 'N/A'}
Volume
{index.volume > 0 ? formatVolume(index.volume) : 'N/A'}
); })}
{/* Market Movers */}
{/* Top Gainers */}
Top Hausses Actions les plus performantes
{gainers?.slice(0, 8).map((stock, index) => (
onTickerClick(stock.symbol)} >
{index + 1}
{stock.symbol}
{stock.name}
{stock.volume && (
Vol: {formatVolume(stock.volume)}
)}
${stock.price?.toFixed(2)}
+{stock.changesPercentage?.toFixed(2)}%
+${stock.change?.toFixed(2)}
))}
{/* Top Losers */}
Top Baisses Actions les plus en baisse
{losers?.slice(0, 8).map((stock, index) => (
onTickerClick(stock.symbol)} >
{index + 1}
{stock.symbol}
{stock.name}
{stock.volume && (
Vol: {formatVolume(stock.volume)}
)}
${stock.price?.toFixed(2)}
{stock.changesPercentage?.toFixed(2)}%
${stock.change?.toFixed(2)}
))}
{/* Most Active */}
Plus Actifs Volume de transactions le plus élevé
{activeStocks?.slice(0, 8).map((stock, index) => { const isPositive = stock.changesPercentage >= 0; return (
onTickerClick(stock.symbol)} >
{index + 1}
{stock.symbol}
{stock.name}
{stock.volume && (
Vol: {formatVolume(stock.volume)}
)}
${stock.price?.toFixed(2)}
{isPositive ? '+' : ''}{stock.changesPercentage?.toFixed(2)}%
{isPositive ? '+' : ''}${stock.change?.toFixed(2)}
); })}
); }