feat: add codex / lore book with 364 entries

Implements a full in-game Codex panel that tracks lore discovery across
seven categories: bosses (72), quests (95), zones (18), equipment (65),
adventurer tiers (32), upgrades (57), and prestige upgrades (25).

Lore entries unlock automatically as players progress — existing
completions are retroactively and silently added on first load. New
discoveries trigger a toast notification and badge counter on the
Codex tab.
This commit is contained in:
2026-03-07 01:17:45 -08:00
committed by Naomi Carrigan
parent b0ed976a1d
commit fd286cd29f
11 changed files with 3838 additions and 6 deletions
@@ -0,0 +1,45 @@
import { useEffect } from "react";
import { CODEX_ENTRIES } from "../../data/codex.js";
import { useGame } from "../../context/GameContext.js";
interface CodexToastItemProps {
entryId: string;
onDismiss: (id: string) => void;
}
const CodexToastItem = ({ entryId, onDismiss }: CodexToastItemProps): React.JSX.Element | null => {
const entry = CODEX_ENTRIES.find((e) => e.id === entryId);
useEffect(() => {
const timer = setTimeout(() => {
onDismiss(entryId);
}, 4000);
return () => { clearTimeout(timer); };
}, [entryId, onDismiss]);
if (!entry) return null;
return (
<div className="codex-toast" onClick={() => { onDismiss(entryId); }}>
<span className="toast-icon">📖</span>
<div className="toast-content">
<span className="toast-label"> Lore Unlocked!</span>
<span className="toast-name">{entry.title}</span>
</div>
</div>
);
};
export const CodexToast = (): React.JSX.Element | null => {
const { newCodexEntryIds, dismissCodexEntry } = useGame();
if (newCodexEntryIds.length === 0) return null;
return (
<div className="achievement-toast-container">
{newCodexEntryIds.map((id) => (
<CodexToastItem key={id} entryId={id} onDismiss={dismissCodexEntry} />
))}
</div>
);
};