158 lines
4.5 KiB
JavaScript
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 />);
|