// Main App — orquestra tudo const { useState: useStateA, useEffect: useEffectA } = React; function App() { const [user, setUser] = useStateA(null); const [progress, setProgress] = useStateA(null); const [view, setView] = useStateA('login'); // login | map | quiz | glossary | mural | trophies const [activeMission, setActiveMission] = useStateA(null); const [pendingResult, setPendingResult] = useStateA(null); const [bootChecked, setBootChecked] = useStateA(false); // Boot useEffectA(() => { (async () => { const id = await window.AppStorage.getCurrentUserId(); if (id) { const users = await window.AppStorage.getUsers(); const u = users.find(x => x.id === id); if (u) { const p = await window.AppStorage.getProgress(u.id); setUser(u); setProgress(p); setView('map'); } } setBootChecked(true); })(); }, []); async function handleLogin(u) { const p = await window.AppStorage.getProgress(u.id); setUser(u); setProgress(p); setView('map'); window.AppStorage.logActivity({ type: 'login', userId: u.id, nick: u.nick, avatar: u.avatar }); } async function handleLogout() { await window.AppStorage.setCurrentUserId(null); setUser(null); setProgress(null); setView('login'); } function openMission(m) { setActiveMission(m); setView('quiz'); window.AppStorage.logActivity({ type: 'mission_start', userId: user.id, nick: user.nick, missionId: m.id, missionTitle: m.title }); } async function handleQuizComplete(result) { // Update progress const newProgress = JSON.parse(JSON.stringify(progress)); if (!newProgress.missions) newProgress.missions = {}; const prev = newProgress.missions[activeMission.id] || {}; const prevStars = Number.isFinite(prev.stars) ? prev.stars : 0; newProgress.missions[activeMission.id] = { stars: Math.max(prevStars, result.stars), completed: prev.completed || result.stars > 0, lastResult: result, resume: null }; // Award mission badge const badges = new Set(newProgress.badges || []); if (result.stars > 0) badges.add(`mission_${activeMission.id}`); if (result.stars === 3) badges.add('mestre_cosmico'); // Lenda Cósmica: 3⭐ em todas as 7 const allThreeStars = window.MISSIONS.every(m => { if (m.id === activeMission.id) return result.stars === 3; return (newProgress.missions[m.id]?.stars || 0) === 3; }); if (allThreeStars) badges.add('lenda_cosmica'); newProgress.badges = Array.from(badges); await window.AppStorage.saveProgress(user.id, newProgress); setProgress(newProgress); setPendingResult(result); window.AppStorage.logActivity({ type: 'mission_complete', userId: user.id, nick: user.nick, missionId: activeMission.id, missionTitle: activeMission.title, stars: result.stars, correctCount: result.correctCount, total: result.total, totalAttempts: result.totalAttempts }); } async function handleShare() { await window.AppStorage.publishToMural({ userId: user.id, nick: user.nick, avatar: user.avatar, missionId: activeMission.id, missionTitle: activeMission.title, missionIcon: activeMission.icon, stars: pendingResult.stars, correctCount: pendingResult.correctCount, total: pendingResult.total }); const np = { ...progress }; np.sharedCount = (np.sharedCount || 0) + 1; const badges = new Set(np.badges || []); badges.add('compartilhador'); np.badges = Array.from(badges); await window.AppStorage.saveProgress(user.id, np); setProgress(np); setPendingResult(null); setActiveMission(null); setView('map'); } function handleSkipShare() { setPendingResult(null); setActiveMission(null); setView('map'); } async function handleGlossaryView() { const np = { ...progress }; np.glossaryViews = (np.glossaryViews || 0) + 1; if (np.glossaryViews >= 5) { const badges = new Set(np.badges || []); badges.add('estudioso'); np.badges = Array.from(badges); } await window.AppStorage.saveProgress(user.id, np); setProgress(np); } if (!bootChecked) { return (
🌍

Preparando a nave...

); } if (view === 'login' || !user) { return ; } return ( <> {view === 'map' && ( setView('glossary')} onOpenMural={() => setView('mural')} onOpenTrophies={() => setView('trophies')} onOpenVideos={() => setView('videos')} onLogout={handleLogout} /> )} {view === 'quiz' && activeMission && !pendingResult && ( { setActiveMission(null); setView('map'); }} onComplete={handleQuizComplete} onOpenGlossary={() => setView('glossary')} /> )} {pendingResult && activeMission && ( )} {view === 'glossary' && ( setView(activeMission ? 'quiz' : 'map')} onView={handleGlossaryView} onNav={(t) => setView(t)} /> )} {view === 'mural' && ( setView('map')} onNav={(t) => setView(t)} /> )} {view === 'trophies' && ( setView('map')} onNav={(t) => setView(t)} /> )} {view === 'videos' && ( setView('map')} onNav={(t) => setView(t)} /> )} ); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render();