Files
elysium/apps/web/src/components/game/BossPanel.tsx
T
hikari a3daed1683 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.
2026-03-06 11:26:19 -08:00

81 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Boss } from "@elysium/types";
import { useGame } from "../../context/GameContext.js";
interface BossCardProps {
boss: Boss;
prestigeCount: number;
}
const BossCard = ({ boss, prestigeCount }: BossCardProps): React.JSX.Element => {
const { attackBoss } = useGame();
const hpPercent = (boss.currentHp / boss.maxHp) * 100;
const isLocked = boss.prestigeRequirement > prestigeCount;
return (
<div className={`boss-card boss-${boss.status}`}>
<div className="boss-info">
<h3>{boss.name}</h3>
<p>{boss.description}</p>
{isLocked && boss.status === "locked" && (
<p className="prestige-lock">🔒 Requires Prestige {boss.prestigeRequirement}</p>
)}
</div>
{boss.status !== "locked" && boss.status !== "defeated" && (
<div className="boss-hp">
<div className="hp-bar">
<div
className="hp-fill"
style={{ width: `${hpPercent.toFixed(1)}%` }}
/>
</div>
<span className="hp-text">
{boss.currentHp.toLocaleString()} / {boss.maxHp.toLocaleString()} HP
</span>
</div>
)}
<div className="boss-rewards">
<span>🪙 {boss.goldReward.toLocaleString()}</span>
{boss.essenceReward > 0 && <span> {boss.essenceReward.toLocaleString()}</span>}
{boss.crystalReward > 0 && <span>💎 {boss.crystalReward.toLocaleString()}</span>}
</div>
{boss.status === "available" || boss.status === "in_progress" ? (
<button
className="attack-button"
onClick={() => { void attackBoss(boss.id); }}
type="button"
>
Attack
</button>
) : null}
{boss.status === "defeated" && (
<span className="boss-badge defeated"> Defeated</span>
)}
</div>
);
};
export const BossPanel = (): React.JSX.Element => {
const { state } = useGame();
if (!state) return <section className="panel"><p>Loading...</p></section>;
return (
<section className="panel boss-panel">
<h2>Boss Encounters</h2>
<div className="boss-list">
{state.bosses.map((boss) => (
<BossCard
key={boss.id}
boss={boss}
prestigeCount={state.prestige.count}
/>
))}
</div>
</section>
);
};