import { useState } from 'react'; import type { Character, Combatant, Encounter, MapToken } from '@/lib/schemas'; import { Button } from '@/components/ui/Button'; import { Select } from '@/components/ui/Input'; import { KIND_COLOR, baseSpec, unplacedPcs, type TokenSpec } from './tokens'; export type { TokenSpec }; /** Left sidebar for one-click placement of party / encounter / blank tokens. */ export function TokenPalette({ characters, encounters, existingTokens, onPlace, onPlaceMany, onClose }: { characters: Character[]; encounters: Encounter[]; existingTokens: MapToken[]; onPlace: (spec: TokenSpec) => void; onPlaceMany: (specs: TokenSpec[]) => void; onClose: () => void; }) { const pcs = characters.filter((c) => c.kind === 'pc'); // Any encounter that has combatants — planned OR active — can supply tokens. const withCombatants = encounters.filter((e) => e.combatants.length > 0); const [encId, setEncId] = useState(''); const selectedEnc = withCombatants.find((e) => e.id === encId) ?? encounters.find((e) => e.status === 'active' && e.combatants.length > 0) ?? withCombatants[0] ?? null; const hasPc = (id: string) => existingTokens.some((t) => t.characterId === id); const hasCombatant = (cb: Combatant) => existingTokens.some((t) => t.combatantId === cb.id || (!t.combatantId && !t.characterId && t.label === cb.name)); const placePc = (c: Character) => onPlace(baseSpec({ label: c.name, color: KIND_COLOR.pc, kind: 'pc', characterId: c.id, hp: c.hp })); const addAllPcs = () => onPlaceMany( unplacedPcs(pcs, existingTokens).map((c, i) => baseSpec({ label: c.name, color: KIND_COLOR.pc, kind: 'pc', characterId: c.id, hp: c.hp, col: i, row: 0 })), ); const placeCombatant = (cb: Combatant) => onPlace(baseSpec({ label: cb.name, color: KIND_COLOR[cb.kind], kind: cb.kind, hp: cb.hp, combatantId: cb.id, ...(cb.characterId ? { characterId: cb.characterId } : {}), })); return ( ); }