/** * @file Codex toast notification component for new lore discoveries. * @copyright nhcarrigan * @license Naomi's Public License * @author Naomi Carrigan */ /* eslint-disable react/no-multi-comp -- Sub-component is tightly coupled to the toast container */ import { type JSX, useEffect } from "react"; import { useGame } from "../../context/gameContext.js"; import { CODEX_ENTRIES } from "../../data/codex.js"; interface CodexToastItemProperties { readonly entryId: string; readonly onDismiss: (id: string)=> void; } /** * Renders a single codex lore toast notification. * @param props - The toast item properties. * @param props.entryId - The codex entry ID to display. * @param props.onDismiss - Callback to dismiss the toast. * @returns The JSX element or null if entry is not found. */ const CodexToastItem = ({ entryId, onDismiss, }: CodexToastItemProperties): JSX.Element | null => { const entry = CODEX_ENTRIES.find((codexEntry) => { return codexEntry.id === entryId; }); useEffect(() => { const timer = setTimeout(() => { onDismiss(entryId); }, 4000); return (): void => { clearTimeout(timer); }; }, [ entryId, onDismiss ]); if (entry === undefined) { return null; } function handleClick(): void { onDismiss(entryId); } return (
{"📖"}
{"✨ Lore Unlocked!"} {entry.title}
); }; /** * Renders the codex toast container with pending lore notifications. * @returns The JSX element or null if there are no pending entries. */ const CodexToast = (): JSX.Element | null => { const { unlockedCodexEntryIds: pendingEntryIds, dismissCodexEntry } = useGame(); if (pendingEntryIds.length === 0) { return null; } return ( <> {pendingEntryIds.map((id) => { return ( ); })} ); }; export { CodexToast };