diff --git a/apps/web/src/components/game/codexPanel.tsx b/apps/web/src/components/game/codexPanel.tsx index 74a1e9a..a3bac2b 100644 --- a/apps/web/src/components/game/codexPanel.tsx +++ b/apps/web/src/components/game/codexPanel.tsx @@ -49,6 +49,40 @@ const sourceTypeFolder: Record = { zone: "zones", }; +/** + * Converts a snake_case ID to a Title Case display name. + * @param id - The snake_case identifier to format. + * @returns The formatted display name. + */ +const formatId = (id: string): string => { + return id.split("_"). + map((word) => { + return word.charAt(0).toUpperCase() + word.slice(1); + }). + join(" "); +}; + +/** + * Generates a human-readable unlock hint for a locked codex entry. + * @param entry - The locked codex entry. + * @returns A string describing how to unlock the entry. + */ +const buildUnlockHint = (entry: CodexEntry): string => { + const name = formatId(entry.sourceId); + switch (entry.sourceType) { + case "boss": return `Defeat ${name}`; + case "quest": return `Complete: ${name}`; + case "equipment": return `Obtain: ${name}`; + case "adventurer": return `Recruit a ${name}`; + case "upgrade": return `Purchase: ${name}`; + case "prestige": return `Purchase runestone upgrade: ${name}`; + case "zone": return `Explore: ${name}`; + case "exploration": return `Discover: ${name}`; + case "recipe": return `Craft: ${name}`; + default: return "Keep playing to unlock"; + } +}; + /** * Renders the codex panel with lore entries grouped by zone. * @returns The JSX element. @@ -136,6 +170,9 @@ const CodexPanel = (): JSX.Element => { {"🔒"} {"???"} +

+ {buildUnlockHint(entry)} +

); }