import { useRef, useEffect } from "react"; import type { Character } from "../types"; import TalentList from "./TalentList"; import SelectDropdown from "./SelectDropdown"; import { getShadowdarkTitle } from "../utils/shadowdark-titles.js"; import styles from "./InfoPanel.module.css"; const CLASSES = ["Fighter", "Priest", "Thief", "Wizard"]; const ANCESTRIES = ["Human", "Elf", "Dwarf", "Halfling", "Goblin", "Half-Orc"]; const ALIGNMENTS = ["Lawful", "Neutral", "Chaotic"]; interface InfoPanelProps { character: Character; mode: "view" | "edit"; onUpdate: (id: number, data: Partial) => void; onAddTalent: ( characterId: number, data: { name: string; description: string; effect?: Record; game_talent_id?: number | null; }, ) => void; onRemoveTalent: (characterId: number, talentId: number) => void; } export default function InfoPanel({ character, mode, onUpdate, onAddTalent, onRemoveTalent, }: InfoPanelProps) { const debounceRef = useRef>(); useEffect(() => { return () => { if (debounceRef.current) clearTimeout(debounceRef.current); }; }, []); function handleField(field: string, value: string | number) { const update: Partial = { [field]: value }; // Auto-update title when class, alignment, or level changes if (field === "class" || field === "alignment" || field === "level") { const newClass = field === "class" ? String(value) : character.class; const newAlignment = field === "alignment" ? String(value) : character.alignment; const newLevel = field === "level" ? Number(value) : character.level; const derived = getShadowdarkTitle(newClass, newAlignment, newLevel); if (derived) update.title = derived; } if (typeof value === "string" && field !== "class" && field !== "alignment") { if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { onUpdate(character.id, update); }, 400); } else { onUpdate(character.id, update); } } return (
onAddTalent(character.id, data)} onRemove={(id) => onRemoveTalent(character.id, id)} mode={mode} />
Info
{mode === "view" ? (
{character.background && (
Background {character.background}
)} {character.deity && (
Deity {character.deity}
)} {character.languages && (
Languages {character.languages}
)}
Alignment {character.alignment}
{character.notes && ( <>
Notes
{character.notes}
)}
) : (
handleField("class", v)} />
handleField("ancestry", v)} />
handleField("level", Number(e.target.value))} />
handleField("alignment", v)} />
handleField("background", e.target.value)} />
handleField("deity", e.target.value)} />
handleField("languages", e.target.value)} />