/** * @file Achievement panel component displaying all game achievements. * @copyright nhcarrigan * @license Naomi's Public License * @author Naomi Carrigan */ /* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to this panel */ 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 { Achievement } from "@elysium/types"; /** * Returns the plural form of a word based on a count. * @param count - The count to check. * @param word - The base word to pluralise. * @returns The pluralised word string. */ const pluralise = (count: number, word: string): string => { return count > 1 ? `${word}s` : word; }; /** * Generates a human-readable condition description for an achievement. * @param achievement - The achievement to describe. * @param formatNumber - The number formatting utility function. * @returns A string describing the achievement condition. */ const conditionDescription = ( achievement: Achievement, formatNumber: (n: number)=> string, ): string => { const { condition } = achievement; switch (condition.type) { case "totalGoldEarned": return `Earn ${formatNumber(condition.amount)} total gold`; case "totalClicks": return `Click ${formatNumber(condition.amount)} times`; case "bossesDefeated": return `Defeat ${String(condition.amount)} ${pluralise(condition.amount, "boss")}`; case "questsCompleted": return `Complete ${String(condition.amount)} ${pluralise(condition.amount, "quest")}`; case "adventurerTotal": return `Recruit ${formatNumber(condition.amount)} total adventurers`; case "prestigeCount": return `Prestige ${String(condition.amount)} ${pluralise(condition.amount, "time")}`; case "equipmentOwned": return `Own ${String(condition.amount)} equipment ${pluralise(condition.amount, "item")}`; default: return "Unknown condition"; } }; interface AchievementCardProperties { readonly achievement: Achievement; readonly formatNumber: (n: number)=> string; } /** * Renders a single achievement card. * @param props - The achievement card properties. * @param props.achievement - The achievement to display. * @param props.formatNumber - The number formatting utility function. * @returns The JSX element. */ const AchievementCard = ({ achievement, formatNumber, }: AchievementCardProperties): JSX.Element => { const isUnlocked = achievement.unlockedAt !== null; const crystals = achievement.reward?.crystals; return (
{achievement.description}
{conditionDescription(achievement, formatNumber)}
{crystals !== undefined &&{"💎 +"} {crystals} {" Crystals"}
}{"Loading..."}
{unlocked.length} {" / "} {achievementList.length} {" unlocked"}