Files
Space-Game/js/app.js
2026-05-25 13:00:20 -04:00

158 lines
4.5 KiB
JavaScript

window.GDD = window.GDD || {};
const GDD = window.GDD;
const FULLSCREEN_PAGES = new Set([
'demo-starmap',
'demo-movement',
'demo-combat',
'demo-market',
'demo-fitting',
'demo-refining',
'demo-progression',
'demo-bounty',
'demo-gamehud',
'demo-chat',
'demo-zora',
'demo-galaxy',
]);
// Map pageId -> component name on GDD
const PAGE_COMPONENTS = {
'overview': 'OverviewPage',
'architecture': 'ArchitecturePage',
'techstack': 'TechStackPage',
'backend': 'BackendPage',
'agents': 'AgentsPage',
'gameplay': 'GameplayPage',
'ships': 'ShipsPage',
'economy': 'EconomyPage',
'social': 'SocialPage',
'ship-ai': 'ShipAIPage',
'roadmap': 'RoadmapPage',
'risks': 'RisksPage',
'demo-gallery': 'DemoGalleryPage',
'demo-starmap': 'StarMapDemo',
'demo-movement': 'ShipMovementDemo',
'demo-combat': 'CombatDemo',
'demo-market': 'MarketDemo',
'demo-fitting': 'FittingDemo',
'demo-refining': 'RefiningDemo',
'demo-progression':'ProgressionDemo',
'demo-bounty': 'BountyDemo',
'demo-gamehud': 'GameHudDemo',
'demo-chat': 'ChatDemo',
'demo-zora': 'ZoraDemo',
'demo-galaxy': 'GalaxyDemo',
};
function App() {
const { page, navigate } = GDD.useRouter();
const [collapsed, setCollapsed] = React.useState(false);
const [loading, setLoading] = React.useState(false);
const [loadError, setLoadError] = React.useState(null);
// Load the page component on demand when navigation changes
React.useEffect(() => {
// Check if component already available (inline loaded pages like overview)
const compName = PAGE_COMPONENTS[page];
if (compName && GDD[compName]) {
GDD._loadedPages = GDD._loadedPages || {};
GDD._loadedPages[page] = true;
return;
}
setLoading(true);
setLoadError(null);
GDD.loadPage(page)
.then(() => setLoading(false))
.catch((err) => {
setLoadError(err.message || 'Failed to load page');
setLoading(false);
});
}, [page]);
// Preload adjacent pages in the background after current page loads
React.useEffect(() => {
if (!loading && !loadError) {
// Preload the next/prev pages after a short delay
const allPageIds = Object.keys(PAGE_COMPONENTS);
const idx = allPageIds.indexOf(page);
if (idx >= 0 && idx < allPageIds.length - 1) {
GDD.preloadPage(allPageIds[idx + 1]);
}
if (idx > 0) {
GDD.preloadPage(allPageIds[idx - 1]);
}
}
}, [page, loading, loadError]);
const renderPage = () => {
if (loading) {
return (
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
height: '60vh', flexDirection: 'column', gap: 'var(--sp-4)',
color: 'var(--muted)', fontFamily: 'var(--font-mono)', fontSize: '0.85rem',
}}>
<div style={{ animation: 'pulse 1.5s ease-in-out infinite' }}>Loading module</div>
</div>
);
}
if (loadError) {
return (
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
height: '60vh', flexDirection: 'column', gap: 'var(--sp-4)',
color: 'var(--red)', fontFamily: 'var(--font-mono)', fontSize: '0.85rem',
}}>
<div>Failed to load page: {loadError}</div>
<button className="btn btn-sm" onClick={() => window.location.reload()}>Reload</button>
</div>
);
}
const compName = PAGE_COMPONENTS[page];
const Comp = compName && GDD[compName];
if (!Comp) return <GDD.OverviewPage />;
return <Comp />;
};
const isFullscreen = FULLSCREEN_PAGES.has(page);
if (isFullscreen) {
return (
<div className="app-shell fullscreen-demo">
<div className="main-area">
<div className="content content--flush">
{renderPage()}
</div>
</div>
</div>
);
}
return (
<div className="app-shell">
<GDD.Sidebar
collapsed={collapsed}
currentPage={page}
onNavigate={navigate}
onToggle={() => setCollapsed(c => !c)}
/>
<div className="main-area">
<GDD.TopBar
collapsed={collapsed}
currentPage={page}
onToggle={() => setCollapsed(c => !c)}
/>
<div className="content">
{renderPage()}
</div>
</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);