'use client';
import { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { motion, AnimatePresence } from 'framer-motion';
import {
TrendingUp, TrendingDown, ChevronDown, ChevronUp, BarChart3,
Zap, Shield, Droplets, Gem, Bitcoin, LineChart, Maximize2, Minimize2
} from 'lucide-react';
import AiOverview from './AiOverview';
interface MarketsPanelProps { data: any; spaceWeather?: any; }
const SECTIONS = [
{ key: 'indices', label: 'INDICES', icon: LineChart },
{ key: 'stocks', label: 'DEFENSE', icon: Shield },
{ key: 'oil', label: 'ENERGY', icon: Droplets },
{ key: 'commodities', label: 'COMMODITIES', icon: Gem },
{ key: 'crypto', label: 'CRYPTO', icon: Bitcoin },
];
function Ticker({ name, data: d }: { name: string; data: any }) {
if (!d) return null;
return (
{name}
{d.price >= 1000 ? `${(d.price / 1000).toFixed(1)}K` : d.price?.toFixed(2)}
{d.up ? : }
{d.change_percent > 0 ? '+' : ''}{d.change_percent?.toFixed(2)}%
);
}
export default function MarketsPanel({ data, spaceWeather }: MarketsPanelProps) {
const [expanded, setExpanded] = useState(true);
const [maximized, setMaximized] = useState(false);
const [activeSection, setActiveSection] = useState('stocks');
const markets = data.markets || {};
// Ensure portal only renders on client
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
const content = (
{expanded && (
{/* Space Weather Banner */}
{spaceWeather && (
SPACE WEATHER
Kp {spaceWeather.kp_index} — {spaceWeather.storm_level}
{spaceWeather.solar_flares?.length > 0 && (
Latest flare: {spaceWeather.solar_flares[0].class}
)}
)}
{/* One-click AI overview of the current market picture */}
{/* Section Tabs — icons instead of emojis */}
{SECTIONS.map(s => {
const Icon = s.icon;
return (
setActiveSection(s.key)}
className={`flex items-center gap-1 px-2.5 py-1.5 rounded text-[9px] font-mono tracking-wider whitespace-nowrap transition-all ${activeSection === s.key ? 'bg-[var(--hover-accent)] text-[var(--gold-primary)] border border-[var(--border-primary)]' : 'text-[var(--text-muted)] hover:text-[var(--text-secondary)] border border-transparent'}`}>
{s.label}
);
})}
{/* SCM Alerts from Markets API */}
{markets.scm_alerts && markets.scm_alerts.length > 0 && (
{markets.scm_alerts.map((alert: string, i: number) => (
{alert}
))}
)}
{/* Ticker List */}
{markets[activeSection] && Object.entries(markets[activeSection]).map(([name, d]) => (
))}
{(!markets[activeSection] || Object.keys(markets[activeSection]).length === 0) && (
Loading {activeSection}...
)}
)}
);
if (maximized && mounted && typeof document !== 'undefined') {
return createPortal(content, document.body);
}
return content;
}