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,73 @@
|
||||
import type { Upgrade } from "@elysium/types";
|
||||
import { useGame } from "../../context/GameContext.js";
|
||||
|
||||
interface UpgradeCardProps {
|
||||
upgrade: Upgrade;
|
||||
currentGold: number;
|
||||
currentEssence: number;
|
||||
}
|
||||
|
||||
const UpgradeCard = ({ upgrade, currentGold, currentEssence }: UpgradeCardProps): React.JSX.Element => {
|
||||
const { buyUpgrade } = useGame();
|
||||
const canAfford =
|
||||
currentGold >= upgrade.costGold && currentEssence >= upgrade.costEssence;
|
||||
|
||||
if (upgrade.purchased) {
|
||||
return (
|
||||
<div className="upgrade-card purchased">
|
||||
<span className="upgrade-name">✅ {upgrade.name}</span>
|
||||
<span className="upgrade-desc">{upgrade.description}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="upgrade-card">
|
||||
<div className="upgrade-info">
|
||||
<h3>{upgrade.name}</h3>
|
||||
<p>{upgrade.description}</p>
|
||||
<p className="upgrade-multiplier">×{upgrade.multiplier} multiplier</p>
|
||||
</div>
|
||||
<div className="upgrade-cost">
|
||||
{upgrade.costGold > 0 && <span>🪙 {upgrade.costGold.toLocaleString()}</span>}
|
||||
{upgrade.costEssence > 0 && <span>✨ {upgrade.costEssence.toLocaleString()}</span>}
|
||||
</div>
|
||||
<button
|
||||
className="buy-button"
|
||||
disabled={!canAfford}
|
||||
onClick={() => { buyUpgrade(upgrade.id); }}
|
||||
type="button"
|
||||
>
|
||||
Buy
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const UpgradePanel = (): React.JSX.Element => {
|
||||
const { state } = useGame();
|
||||
|
||||
if (!state) return <section className="panel"><p>Loading...</p></section>;
|
||||
|
||||
const availableUpgrades = state.upgrades.filter((u) => u.unlocked);
|
||||
|
||||
return (
|
||||
<section className="panel upgrade-panel">
|
||||
<h2>Upgrades</h2>
|
||||
{availableUpgrades.length === 0 ? (
|
||||
<p className="empty-state">No upgrades available yet — keep adventuring!</p>
|
||||
) : (
|
||||
<div className="upgrade-list">
|
||||
{availableUpgrades.map((upgrade) => (
|
||||
<UpgradeCard
|
||||
key={upgrade.id}
|
||||
upgrade={upgrade}
|
||||
currentGold={state.resources.gold}
|
||||
currentEssence={state.resources.essence}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user