/** * @file Upgrade panel component for purchasing game upgrades. * @copyright nhcarrigan * @license Naomi's Public License * @author Naomi Carrigan */ /* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to the panel */ /* eslint-disable max-lines-per-function -- Complex component with many render paths */ /* eslint-disable complexity -- UpgradeCard has many conditional render paths for states */ import { type JSX, useState } from "react"; import { useGame } from "../../context/gameContext.js"; import { cdnImage } from "../../utils/cdn.js"; import { LockToggle } from "../ui/lockToggle.js"; import type { Upgrade } from "@elysium/types"; interface UpgradeCardProperties { readonly upgrade: Upgrade; readonly currentGold: number; readonly currentEssence: number; readonly currentCrystals: number; readonly unlockHint: string | undefined; readonly formatNumber: (n: number)=> string; } /** * Renders a single upgrade card. * @param props - The upgrade card properties. * @param props.upgrade - The upgrade data. * @param props.currentGold - The current gold amount. * @param props.currentEssence - The current essence amount. * @param props.currentCrystals - The current crystals amount. * @param props.unlockHint - Optional hint for how to unlock this upgrade. * @param props.formatNumber - The number formatting utility function. * @returns The JSX element. */ const UpgradeCard = ({ upgrade, currentGold, currentEssence, currentCrystals, unlockHint, formatNumber, }: UpgradeCardProperties): JSX.Element => { const { buyUpgrade } = useGame(); const canAfford = currentGold >= upgrade.costGold && currentEssence >= upgrade.costEssence && currentCrystals >= upgrade.costCrystals; function handleBuy(): void { buyUpgrade(upgrade.id); } if (upgrade.unlocked && upgrade.purchased) { return (
{upgrade.name} {"✅ "} {upgrade.name} {upgrade.description}
); } if (upgrade.unlocked) { return (
{upgrade.name}

{upgrade.name}

{upgrade.description}

{"×"} {upgrade.multiplier} {" multiplier"}

{upgrade.costGold > 0 && {"🪙 "} {formatNumber(upgrade.costGold)} } {upgrade.costEssence > 0 && {"✨ "} {formatNumber(upgrade.costEssence)} } {upgrade.costCrystals > 0 && {"💎 "} {formatNumber(upgrade.costCrystals)} }
); } return (
{upgrade.name}

{"🔒 "} {upgrade.name}

{upgrade.description}

{"×"} {upgrade.multiplier} {" multiplier"}

{upgrade.costGold > 0 && {"🪙 "} {formatNumber(upgrade.costGold)} } {upgrade.costEssence > 0 && {"✨ "} {formatNumber(upgrade.costEssence)} } {upgrade.costCrystals > 0 && {"💎 "} {formatNumber(upgrade.costCrystals)} }
{"Locked"} {unlockHint === undefined ? null :

{unlockHint}

}
); }; /** * Renders the upgrade panel with all available, locked, and purchased upgrades. * @returns The JSX element. */ const UpgradePanel = (): JSX.Element => { const { state, formatNumber } = useGame(); const [ showLocked, setShowLocked ] = useState(true); if (state === null) { return (

{"Loading..."}

); } const { bosses, quests, upgrades, resources } = state; const purchased = upgrades.filter((upgrade) => { return upgrade.purchased; }); const available = upgrades.filter((upgrade) => { return upgrade.unlocked && !upgrade.purchased; }); const locked = upgrades.filter((upgrade) => { return !upgrade.unlocked; }); const upgradeUnlockHints = new Map(); for (const { upgradeRewards, name: bossName } of bosses) { for (const upgradeId of upgradeRewards) { upgradeUnlockHints.set(upgradeId, `⚔️ Defeat: ${bossName}`); } } for (const { rewards, name: questName } of quests) { for (const reward of rewards) { if ( reward.type === "upgrade" && reward.targetId !== undefined && !upgradeUnlockHints.has(reward.targetId) ) { upgradeUnlockHints.set(reward.targetId, `📜 Complete: ${questName}`); } } } function handleToggle(): void { setShowLocked((current) => { return !current; }); } return (

{"Upgrades"}

{purchased.length} {" / "} {upgrades.length} {" purchased"}

{upgrades.length === 0 ?

{"No upgrades available yet — keep adventuring!"}

:
{available.map((upgrade) => { return ( ); })} {purchased.map((upgrade) => { return ( ); })} {showLocked ? locked.map((upgrade) => { return ( ); }) : null}
}
); }; export { UpgradePanel };