import { useState, useEffect } from 'react'; import { ChevronLeft, ChevronRight, ChevronDown, ChevronUp, Search, Globe, Rocket, Moon, Asterisk, Sparkles } from 'lucide-react'; import type { CelestialBody } from '../types'; interface ProbeListProps { probes: CelestialBody[]; planets: CelestialBody[]; onBodySelect: (body: CelestialBody | null) => void; selectedBody: CelestialBody | null; onResetCamera: () => void; } export function ProbeList({ probes, planets, onBodySelect, selectedBody, onResetCamera }: ProbeListProps) { const [isCollapsed, setIsCollapsed] = useState(true); // 默认关闭 const [searchTerm, setSearchTerm] = useState(''); const [expandedGroup, setExpandedGroup] = useState(null); // 只允许一个分组展开 // Auto-collapse when a body is selected (focus mode) useEffect(() => { if (selectedBody) { setIsCollapsed(true); } }, [selectedBody]); // Calculate distance for sorting const calculateDistance = (body: CelestialBody) => { const pos = body.positions[0]; return Math.sqrt(pos.x ** 2 + pos.y ** 2 + pos.z ** 2); }; const processBodies = (list: CelestialBody[]) => { return list .filter(b => (b.name_zh || b.name).toLowerCase().includes(searchTerm.toLowerCase()) && b.type !== 'star' // Exclude Sun from list ) .map(body => ({ body, distance: calculateDistance(body) })) .sort((a, b) => a.distance - b.distance); }; // Group bodies by type const allBodies = [...planets, ...probes]; const processedBodies = processBodies(allBodies); const planetList = processedBodies.filter(({ body }) => body.type === 'planet'); const dwarfPlanetList = processedBodies.filter(({ body }) => body.type === 'dwarf_planet'); const satelliteList = processedBodies.filter(({ body }) => body.type === 'satellite'); const probeList = processedBodies.filter(({ body }) => body.type === 'probe'); const cometList = processedBodies.filter(({ body }) => body.type === 'comet'); const toggleGroup = (groupName: string) => { // 如果点击的是当前展开的分组,则收起;否则切换到新分组 setExpandedGroup(prev => prev === groupName ? null : groupName); }; return (
{/* Main Content Panel */}
{/* Header & Search */}

天体导航

setSearchTerm(e.target.value)} className="w-full bg-white/5 border border-white/10 rounded-lg pl-9 pr-3 py-2 text-xs text-white placeholder-gray-500 focus:outline-none focus:border-[#238636]/50 transition-colors" />
{/* List Content */}
{/* Planets Group */} {planetList.length > 0 && ( } count={planetList.length} bodies={planetList} isExpanded={expandedGroup === 'planet'} onToggle={() => toggleGroup('planet')} selectedBody={selectedBody} onBodySelect={onBodySelect} /> )} {/* Dwarf Planets Group */} {dwarfPlanetList.length > 0 && ( } count={dwarfPlanetList.length} bodies={dwarfPlanetList} isExpanded={expandedGroup === 'dwarf_planet'} onToggle={() => toggleGroup('dwarf_planet')} selectedBody={selectedBody} onBodySelect={onBodySelect} /> )} {/* Satellites Group */} {satelliteList.length > 0 && ( } count={satelliteList.length} bodies={satelliteList} isExpanded={expandedGroup === 'satellite'} onToggle={() => toggleGroup('satellite')} selectedBody={selectedBody} onBodySelect={onBodySelect} /> )} {/* Probes Group */} {probeList.length > 0 && ( } count={probeList.length} bodies={probeList} isExpanded={expandedGroup === 'probe'} onToggle={() => toggleGroup('probe')} selectedBody={selectedBody} onBodySelect={onBodySelect} /> )} {/* Comets Group */} {cometList.length > 0 && ( } count={cometList.length} bodies={cometList} isExpanded={expandedGroup === 'comet'} onToggle={() => toggleGroup('comet')} selectedBody={selectedBody} onBodySelect={onBodySelect} /> )} {/* No results message */} {processedBodies.length === 0 && (
未找到匹配的天体
)}
{/* Toggle Button (Attached to the side) */}
); } // Group component for collapsible body lists function BodyGroup({ title, icon, count, bodies, isExpanded, onToggle, selectedBody, onBodySelect }: { title: string; icon: React.ReactNode; count: number; bodies: Array<{ body: CelestialBody; distance: number }>; isExpanded: boolean; onToggle: () => void; selectedBody: CelestialBody | null; onBodySelect: (body: CelestialBody) => void; }) { return (
{/* Group Header */} {/* Group Content */} {isExpanded && (
{bodies.map(({ body, distance }) => ( onBodySelect(body)} /> ))}
)}
); } function BodyItem({ body, distance, isSelected, onClick }: { body: CelestialBody, distance: number, isSelected: boolean, onClick: () => void }) { const isInactive = body.is_active === false; return ( ); }