generated from nhcarrigan/template
924b9f541d
Adds pronouns, guildName, and guildDescription fields to the player profile. A new Character tab provides an in-game view/edit panel for character and guild lore. Closes #16
143 lines
5.6 KiB
TypeScript
143 lines
5.6 KiB
TypeScript
import { useState } from "react";
|
||
import { useGame } from "../../context/GameContext.js";
|
||
import { ResourceBar } from "../ui/ResourceBar.js";
|
||
import { AboutPanel } from "./AboutPanel.js";
|
||
import { AchievementPanel } from "./AchievementPanel.js";
|
||
import { AchievementToast } from "./AchievementToast.js";
|
||
import { AdventurerPanel } from "./AdventurerPanel.js";
|
||
import { BattleModal } from "./BattleModal.js";
|
||
import { BossPanel } from "./BossPanel.js";
|
||
import { ClickArea } from "./ClickArea.js";
|
||
import { CodexPanel } from "./CodexPanel.js";
|
||
import { CodexToast } from "./CodexToast.js";
|
||
import { EditProfileModal } from "./EditProfileModal.js";
|
||
import { EquipmentPanel } from "./EquipmentPanel.js";
|
||
import { OfflineModal } from "./OfflineModal.js";
|
||
import { PrestigePanel } from "./PrestigePanel.js";
|
||
import { ApotheosisPanel } from "./ApotheosisPanel.js";
|
||
import { TranscendencePanel } from "./TranscendencePanel.js";
|
||
import { QuestPanel } from "./QuestPanel.js";
|
||
import { StatisticsPanel } from "./StatisticsPanel.js";
|
||
import { UpgradePanel } from "./UpgradePanel.js";
|
||
import { DailyChallengePanel } from "./DailyChallengePanel.js";
|
||
import { ExplorationPanel } from "./ExplorationPanel.js";
|
||
import { CharacterSheetPanel } from "./CharacterSheetPanel.js";
|
||
import { CraftingPanel } from "./CraftingPanel.js";
|
||
|
||
type Tab = "adventurers" | "upgrades" | "quests" | "bosses" | "equipment" | "achievements" | "prestige" | "transcendence" | "apotheosis" | "statistics" | "daily" | "codex" | "about" | "exploration" | "crafting" | "character";
|
||
|
||
const BASE_TABS: { id: Tab; label: string }[] = [
|
||
{ id: "adventurers", label: "βοΈ Adventurers" },
|
||
{ id: "upgrades", label: "π§ Upgrades" },
|
||
{ id: "quests", label: "π Quests" },
|
||
{ id: "bosses", label: "πΉ Bosses" },
|
||
{ id: "equipment", label: "π‘οΈ Equipment" },
|
||
{ id: "exploration", label: "πΊοΈ Exploration" },
|
||
{ id: "crafting", label: "βοΈ Crafting" },
|
||
{ id: "daily", label: "π
Daily" },
|
||
{ id: "prestige", label: "β Prestige" },
|
||
{ id: "transcendence", label: "π Transcendence" },
|
||
{ id: "apotheosis", label: "β¨ Apotheosis" },
|
||
{ id: "statistics", label: "π Statistics" },
|
||
{ id: "character", label: "π Character" },
|
||
{ id: "achievements", label: "π Achievements" },
|
||
{ id: "codex", label: "π Codex" },
|
||
{ id: "about", label: "βΉοΈ About" },
|
||
];
|
||
|
||
export const GameLayout = (): React.JSX.Element => {
|
||
const { state, isLoading, error, battleResult, dismissBattle, lastSavedAt, isSyncing, forceSync, newCodexEntryIds } = useGame();
|
||
const [activeTab, setActiveTab] = useState<Tab>("adventurers");
|
||
const [editingProfile, setEditingProfile] = useState(false);
|
||
|
||
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>;
|
||
|
||
const profileUrl = `/profile/${state.player.discordId}`;
|
||
|
||
return (
|
||
<div className="game-layout">
|
||
<ResourceBar
|
||
resources={state.resources}
|
||
runestones={state.prestige.runestones}
|
||
prestigeCount={state.prestige.count}
|
||
transcendenceCount={state.transcendence?.count ?? 0}
|
||
apotheosisCount={state.apotheosis?.count ?? 0}
|
||
profileUrl={profileUrl}
|
||
onEditProfile={() => { setEditingProfile(true); }}
|
||
lastSavedAt={lastSavedAt}
|
||
isSyncing={isSyncing}
|
||
onForceSync={forceSync}
|
||
/>
|
||
<OfflineModal />
|
||
<AchievementToast />
|
||
<CodexToast />
|
||
{battleResult && (
|
||
<BattleModal battle={battleResult} onDismiss={dismissBattle} />
|
||
)}
|
||
{editingProfile && (
|
||
<EditProfileModal onClose={() => { setEditingProfile(false); }} />
|
||
)}
|
||
|
||
<div className="game-main">
|
||
<aside className="game-sidebar">
|
||
<ClickArea />
|
||
<p className="game-copyright">Β© NHCarrigan</p>
|
||
</aside>
|
||
|
||
<main className="game-content">
|
||
<nav className="tab-bar">
|
||
{BASE_TABS.map((tab) => (
|
||
<button
|
||
key={tab.id}
|
||
className={`tab-button ${activeTab === tab.id ? "active" : ""}`}
|
||
onClick={() => { setActiveTab(tab.id); }}
|
||
type="button"
|
||
>
|
||
{tab.label}
|
||
{tab.id === "codex" && newCodexEntryIds.length > 0 && (
|
||
<span className="tab-badge">{newCodexEntryIds.length}</span>
|
||
)}
|
||
</button>
|
||
))}
|
||
</nav>
|
||
|
||
<div className="tab-content">
|
||
{activeTab === "adventurers" && <AdventurerPanel />}
|
||
{activeTab === "upgrades" && <UpgradePanel />}
|
||
{activeTab === "quests" && <QuestPanel />}
|
||
{activeTab === "bosses" && <BossPanel />}
|
||
{activeTab === "equipment" && <EquipmentPanel />}
|
||
{activeTab === "achievements" && <AchievementPanel />}
|
||
{activeTab === "prestige" && <PrestigePanel />}
|
||
{activeTab === "transcendence" && <TranscendencePanel />}
|
||
{activeTab === "apotheosis" && <ApotheosisPanel />}
|
||
{activeTab === "exploration" && <ExplorationPanel />}
|
||
{activeTab === "crafting" && <CraftingPanel />}
|
||
{activeTab === "statistics" && <StatisticsPanel />}
|
||
{activeTab === "daily" && <DailyChallengePanel />}
|
||
{activeTab === "character" && <CharacterSheetPanel />}
|
||
{activeTab === "codex" && <CodexPanel />}
|
||
{activeTab === "about" && <AboutPanel />}
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|