Initial commit
This commit is contained in:
157
js/app.js
Normal file
157
js/app.js
Normal file
@@ -0,0 +1,157 @@
|
||||
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 />);
|
||||
Reference in New Issue
Block a user