generated from nhcarrigan/template
feat: initial elysium idle game prototype
Sets up the full monorepo with pnpm workspaces. Includes shared types package, Hono API with Discord OAuth/JWT auth, Prisma v6 + MongoDB Atlas, and React + Vite frontend with game loop, five tabs, and Discord-linked save/load.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { useState } from "react";
|
||||
import { useGame } from "../../context/GameContext.js";
|
||||
import { ResourceBar } from "../ui/ResourceBar.js";
|
||||
import { AdventurerPanel } from "./AdventurerPanel.js";
|
||||
import { BossPanel } from "./BossPanel.js";
|
||||
import { ClickArea } from "./ClickArea.js";
|
||||
import { OfflineModal } from "./OfflineModal.js";
|
||||
import { PrestigePanel } from "./PrestigePanel.js";
|
||||
import { QuestPanel } from "./QuestPanel.js";
|
||||
import { UpgradePanel } from "./UpgradePanel.js";
|
||||
|
||||
type Tab = "adventurers" | "upgrades" | "quests" | "bosses" | "prestige";
|
||||
|
||||
const TABS: { id: Tab; label: string }[] = [
|
||||
{ id: "adventurers", label: "⚔️ Adventurers" },
|
||||
{ id: "upgrades", label: "🔧 Upgrades" },
|
||||
{ id: "quests", label: "📜 Quests" },
|
||||
{ id: "bosses", label: "👹 Bosses" },
|
||||
{ id: "prestige", label: "⭐ Prestige" },
|
||||
];
|
||||
|
||||
export const GameLayout = (): React.JSX.Element => {
|
||||
const { state, isLoading, error } = useGame();
|
||||
const [activeTab, setActiveTab] = useState<Tab>("adventurers");
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="loading-screen">
|
||||
<p>Loading your adventure...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="error-screen">
|
||||
<p>Error: {error}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!state) return <div className="loading-screen"><p>Loading...</p></div>;
|
||||
|
||||
return (
|
||||
<div className="game-layout">
|
||||
<ResourceBar
|
||||
resources={state.resources}
|
||||
prestigeCount={state.prestige.count}
|
||||
/>
|
||||
<OfflineModal />
|
||||
|
||||
<div className="game-main">
|
||||
<aside className="game-sidebar">
|
||||
<ClickArea />
|
||||
</aside>
|
||||
|
||||
<main className="game-content">
|
||||
<nav className="tab-bar">
|
||||
{TABS.map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
className={`tab-button ${activeTab === tab.id ? "active" : ""}`}
|
||||
onClick={() => { setActiveTab(tab.id); }}
|
||||
type="button"
|
||||
>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="tab-content">
|
||||
{activeTab === "adventurers" && <AdventurerPanel />}
|
||||
{activeTab === "upgrades" && <UpgradePanel />}
|
||||
{activeTab === "quests" && <QuestPanel />}
|
||||
{activeTab === "bosses" && <BossPanel />}
|
||||
{activeTab === "prestige" && <PrestigePanel />}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user