Let's Talk
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react'; import { Sun as SunIcon, Orbit, Thermometer, Scale, ArrowRight, X, Compass, Moon as MoonIcon, Globe, Sparkles, Rocket, Loader2, BookOpen, Save, CheckCircle2, ZoomIn, ZoomOut, Maximize, Move, ChevronRight, Users } from 'lucide-react'; // Firebase Imports import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, getDoc, collection, onSnapshot } from 'firebase/firestore'; // --- Configuration & Constants --- const firebaseConfig = JSON.parse(__firebase_config || '{}'); const appId = typeof __app_id !== 'undefined' ? __app_id : 'solar-system-guide'; const apiKey = ""; // Gemini API Key const GEN_MODEL = "gemini-2.5-flash-preview-09-2025"; const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const SUN_DATA = { name: "The Sun", color: "#ffcc00", style: "radial-gradient(circle at center, #ffffff 0%, #fff9c4 15%, #ffeb3b 40%, #f57c00 80%, #e65100 100%)", size: 96, description: "The Sun is the star at the center of our Solar System. It is a nearly perfect sphere of hot plasma, heated to incandescence by nuclear fusion reactions in its core.", diameter: "1.39M km", distance: "System Center", gravity: "274 m/s²", temp: "5,505°C (Surface)", moons: "8 Primary Planets", type: "Yellow Dwarf (G2V)" }; const PLANET_DATA = [ { name: "Mercury", color: "#8c8c8c", style: "radial-gradient(circle at 30% 30%, #b0b0b0, #666666 60%, #333333)", size: 10, description: "The smallest planet, Mercury is a cratered world scorched by the Sun.", diameter: "4,879 km", distance: "57.9M km", gravity: "3.7 m/s²", temp: "167°C", moons: 0, type: "Terrestrial" }, { name: "Venus", color: "#e3bb76", style: "radial-gradient(circle at 30% 30%, #fff5d1, #e3bb76 50%, #8a6a3d)", size: 16, description: "Venus is Earth's sister planet, with a runaway greenhouse effect.", diameter: "12,104 km", distance: "108.2M km", gravity: "8.9 m/s²", temp: "464°C", moons: 0, type: "Terrestrial" }, { name: "Earth", color: "#2271b3", style: "radial-gradient(circle at 30% 30%, #4facfe 0%, #00f2fe 10%, #2271b3 40%, #0a3d62 80%, #000 100%)", size: 18, description: "Our home, uniquely rich in liquid water and life.", diameter: "12,756 km", distance: "149.6M km", gravity: "9.8 m/s²", temp: "15°C", moons: 1, type: "Terrestrial" }, { name: "Mars", color: "#e27b58", style: "radial-gradient(circle at 30% 30%, #ff9a7b, #e27b58 50%, #8b3a1a 90%, #000)", size: 12, description: "The Red Planet, home to ancient riverbeds and massive volcanoes.", diameter: "6,792 km", distance: "227.9M km", gravity: "3.7 m/s²", temp: "-65°C", moons: 2, type: "Terrestrial" }, { name: "Jupiter", color: "#d39c7e", style: "linear-gradient(170deg, #6b4c3a 0%, #d39c7e 20%, #f3e5ab 40%, #d39c7e 60%, #6b4c3a 80%, #2b1d14 100%)", size: 48, description: "The king of planets, a gas giant massive enough to hold 1,300 Earths.", diameter: "142,984 km", distance: "778.6M km", gravity: "24.8 m/s²", temp: "-110°C", moons: 95, type: "Gas Giant" }, { name: "Saturn", color: "#c5ab6e", style: "linear-gradient(180deg, #8a7b52 0%, #c5ab6e 30%, #e8d5a7 50%, #c5ab6e 70%, #6b5d3a 100%)", size: 42, hasRings: true, description: "Famous for its spectacular ring system made of ice and rock particles.", diameter: "120,536 km", distance: "1.4B km", gravity: "10.4 m/s²", temp: "-140°C", moons: 146, type: "Gas Giant" }, { name: "Uranus", color: "#bbe1e4", style: "radial-gradient(circle at 30% 30%, #e0f7f8, #bbe1e4 50%, #7da9ac 90%, #000)", size: 28, description: "An ice giant that rotates on its side. Atmosphere contains hydrogen and helium.", diameter: "51,118 km", distance: "2.9B km", gravity: "8.7 m/s²", temp: "-195°C", moons: 28, type: "Ice Giant" }, { name: "Neptune", color: "#6081ff", style: "radial-gradient(circle at 30% 30%, #a2b5ff, #6081ff 50%, #2d4499 90%, #000)", size: 27, description: "A dark, cold world whipped by supersonic winds, the farthest major planet.", diameter: "49,528 km", distance: "4.5B km", gravity: "11.0 m/s²", temp: "-201°C", moons: 16, type: "Ice Giant" } ]; // --- Utilities --- async function callGemini(prompt, systemInstruction = "") { let delay = 1000; for (let i = 0; i < 5; i++) { try { const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${GEN_MODEL}:generateContent?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }], systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : undefined }) }); if (!response.ok) throw new Error(`Status: ${response.status}`); const data = await response.json(); return data.candidates?.[0]?.content?.parts?.[0]?.text || "Communication failed."; } catch (error) { if (i === 4) return "Network error. Deep space uplink lost."; await new Promise(r => setTimeout(r, delay)); delay *= 2; } } } // Clean and format AI Text const FormattedAIResponse = ({ text }) => { if (!text) return null; const stripHtml = (str) => str.replace(/<[^>]*>?/gm, ''); const cleanMarkdown = (str) => str.replace(/\*\*(.*?)\*\*/g, '$1').replace(/\*(.*?)\*/g, '$1').replace(/###?\s+(.*)/g, '$1').replace(/__/g, ''); const lines = text.split('\n'); return (
{lines.map((line, idx) => { const cleaned = cleanMarkdown(stripHtml(line)).trim(); if (!cleaned) return
; const isHeader = line.startsWith('#') || (cleaned.length < 40 && cleaned.endsWith(':')); const isBullet = line.trim().startsWith('*') || line.trim().startsWith('-'); if (isHeader) return

{cleaned.replace(':', '')}

; if (isBullet) return (

{cleaned.replace(/^[*-]\s*/, '')}

); return

{cleaned}

; })}
); }; // --- Components --- const PlanetInfoCard = ({ planet, onClose, user }) => { const [aiInsight, setAiInsight] = useState(""); const [loading, setLoading] = useState(false); const [mode, setMode] = useState("data"); const [teamLog, setTeamLog] = useState(""); const [lastSaved, setLastSaved] = useState(false); // Collaboration Logic: Sync with Firestore useEffect(() => { if (!planet || !user) return; const path = doc(db, 'artifacts', appId, 'public', 'data', `team_log_${planet.name.replace(/\s+/g, '_')}`); const unsubscribe = onSnapshot(path, (snapshot) => { if (snapshot.exists()) setTeamLog(snapshot.data().text || ""); }, (err) => console.error("Sync error:", err)); setAiInsight(""); setMode("data"); return () => unsubscribe(); }, [planet, user]); if (!planet) return null; const handleAI = async (type) => { setLoading(true); setMode(type); const p = type === 'guide' ? `Provide a unique scientific discovery about ${planet.name}. IMPORTANT: Output plain text only. No HTML tags or Markdown asterisks.` : `Draft a space agency mission brief for ${planet.name}. IMPORTANT: Output plain text only. No HTML tags or Markdown asterisks.`; const res = await callGemini(p, "You are a professional astronomer."); setAiInsight(res); setLoading(false); }; const handleLogChange = async (e) => { const val = e.target.value; setTeamLog(val); if (!user) return; try { const path = doc(db, 'artifacts', appId, 'public', 'data', `team_log_${planet.name.replace(/\s+/g, '_')}`); await setDoc(path, { text: val, lastUpdated: new Date().toISOString(), lastEditedBy: user.uid }); setLastSaved(true); setTimeout(() => setLastSaved(false), 2000); } catch (err) { console.error("Log save failed", err); } }; return (

{planet.name}

{planet.type}
{mode === "data" ? (

{planet.description}

Distance
{planet.distance}
Diameter
{planet.diameter}
Temp
{planet.temp}
Gravity
{planet.gravity}
Celestial Objects
{planet.moons}
) : mode === "team" ? (

Collaboration Hub

{lastSaved && SYNCED}

Shared in real-time with all explorers viewing this planet.