'use client'; import { memo, useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Plane, Satellite, Sun, AlertTriangle, Camera, CloudLightning, Ship, Network, Database, Ghost, Flame, Tv, Radio, Mountain, Anchor, Radar } from 'lucide-react'; interface LayerPanelProps { data: any; activeLayers: any; setActiveLayers: React.Dispatch>; isMobile?: boolean; theme?: 'core' | 'ghost'; setTheme?: (theme: 'core' | 'ghost') => void; } const LAYER_GROUPS = [ { label: 'SDK', fullLabel: 'OSIRIS SDK', icon: Database, layers: [ { key: 'sdk_sea', label: 'Maritime Lines', dataKey: 'sdk_entities' }, ], }, { label: 'AVIATION', fullLabel: 'AVIATION', icon: Plane, layers: [ { key: 'flights', label: 'Commercial', dataKey: 'commercial_flights' }, { key: 'private', label: 'Private', dataKey: 'private_flights' }, { key: 'jets', label: 'Private Jets', dataKey: 'private_jets' }, { key: 'military', label: 'Military', dataKey: 'military_flights' }, ], }, { label: 'MARITIME', fullLabel: 'MARITIME', icon: Ship, layers: [ { key: 'maritime', label: 'Maritime / Naval', dataKey: 'maritime_ships,maritime_ports,maritime_chokepoints' }, ], }, { label: 'SPACE', fullLabel: 'SPACE TRACKING', icon: Satellite, layers: [ { key: 'satellites', label: 'All Satellites', dataKey: 'satellites' }, { key: 'sat_comms', label: 'Starlink / Comms', dataKey: 'satellites', catKey: 'comms' }, { key: 'sat_military', label: 'Military / Intel', dataKey: 'satellites', catKey: 'military' }, { key: 'sat_navigation', label: 'GPS / Navigation', dataKey: 'satellites', catKey: 'navigation' }, { key: 'sat_earth', label: 'Earth Observation', dataKey: 'satellites', catKey: 'earth_obs' }, { key: 'sat_science', label: 'Stations / Telescopes', dataKey: 'satellites', catKey: 'science' }, ], }, { label: 'SURVEIL', fullLabel: 'SURVEILLANCE', icon: Camera, layers: [ { key: 'cctv', label: 'CCTV Cameras', dataKey: 'cameras' }, { key: 'live_news', label: 'Live News Feeds', dataKey: 'live_feeds' }, { key: 'news_intel', label: 'SIGINT News', dataKey: 'sigint_news' }, ], }, { label: 'HAZARD', fullLabel: 'NATURAL HAZARDS', icon: CloudLightning, layers: [ { key: 'earthquakes', label: 'Earthquakes', dataKey: 'earthquakes' }, { key: 'fires', label: 'Active Fires', dataKey: 'fires' }, { key: 'weather', label: 'Severe Weather', dataKey: 'weather_events' }, ], }, { label: 'THREAT', fullLabel: 'THREATS & INTEL', icon: AlertTriangle, layers: [ { key: 'infrastructure', label: 'Nuclear Facilities', dataKey: 'infrastructure' }, { key: 'global_incidents', label: 'Global Incidents', dataKey: 'gdelt' }, { key: 'gps_jamming', label: 'GPS Jamming', dataKey: 'gps_jamming' }, ], }, { label: 'NETWORK', fullLabel: 'NETWORK INTEL', icon: Network, layers: [ { key: 'malware', label: 'Live Malware', dataKey: 'malware_threats' }, ], }, { label: 'RESOURCE', fullLabel: 'RESOURCE INTEL', icon: Mountain, layers: [ { key: 'mining', label: 'Mining Companies', dataKey: 'mining_companies' }, { key: 'ram_fabs', label: 'Memory / RAM Fabs', dataKey: 'ram_companies' }, ], }, { label: 'DISPLAY', fullLabel: 'DISPLAY', icon: Sun, layers: [ { key: 'day_night', label: 'Day / Night Cycle', dataKey: '' }, { key: 'terrain_3d', label: '3D Terrain & Buildings', dataKey: '' }, ], }, ]; /* ── Minimal Toggle Switch ── */ function ToggleSwitch({ active, onClick }: { active: boolean; onClick: () => void }) { return ( ); } function LayerPanel({ data, activeLayers, setActiveLayers, isMobile, theme = 'core', setTheme }: LayerPanelProps) { const [hoveredGroup, setHoveredGroup] = useState(null); const toggle = (key: string) => setActiveLayers((prev: any) => ({ ...prev, [key]: !prev[key] })); const getCount = (dk: string, catKey?: string): number | null => { if (!dk) return null; if (catKey && data.category_counts) { return data.category_counts[catKey] || 0; } let total = 0; let found = false; for (const k of dk.split(',')) { if (data[k] && Array.isArray(data[k])) { total += data[k].length; found = true; } } return found ? total : null; }; /* ── MOBILE ── */ if (isMobile) { return (
{LAYER_GROUPS.map((group) => (
{group.fullLabel}
{group.layers.map((layer) => { const isLayerActive = activeLayers[layer.key]; const count = getCount(layer.dataKey, layer.catKey); return (
toggle(layer.key)} /> {layer.label} {count !== null && ( {count.toLocaleString()} )}
); })}
))} {/* MOBILE GHOST TOGGLE */} {setTheme && (
Ghost Protocol
)}
); } /* ── DESKTOP ── */ return (
{LAYER_GROUPS.map((group) => { const groupActive = group.layers.some(l => activeLayers[l.key]); const isHovered = hoveredGroup === group.label; const Icon = group.icon; return (
setHoveredGroup(group.label)} onMouseLeave={() => setHoveredGroup(null)} > {/* Icon Button */}
{/* Flyout (LEFT side) */} {isHovered && (
{group.fullLabel}
{group.layers.map((layer) => { const isLayerActive = activeLayers[layer.key]; const count = getCount(layer.dataKey, layer.catKey); return (
toggle(layer.key)} > {}} /> {layer.label} {count !== null && ( {count.toLocaleString()} )}
); })}
)}
); })}
{/* Subtle separator */}
{/* Ghost Protocol Toggle */} {setTheme && ( )} ); } export default memo(LayerPanel);