import type { PlayerCharacter, PlayerCharacterId } from "@initiative/domain"; import { Pencil, Plus, Trash2, X } from "lucide-react"; import { useEffect, useRef } from "react"; import { PLAYER_COLOR_HEX, PLAYER_ICON_MAP } from "./player-icon-map"; import { Button } from "./ui/button"; import { ConfirmButton } from "./ui/confirm-button"; interface PlayerManagementProps { open: boolean; onClose: () => void; characters: readonly PlayerCharacter[]; onEdit: (pc: PlayerCharacter) => void; onDelete: (id: PlayerCharacterId) => void; onCreate: () => void; } export function PlayerManagement({ open, onClose, characters, onEdit, onDelete, onCreate, }: Readonly) { const dialogRef = useRef(null); useEffect(() => { const dialog = dialogRef.current; if (!dialog) return; if (open && !dialog.open) { dialog.showModal(); } else if (!open && dialog.open) { dialog.close(); } }, [open]); useEffect(() => { const dialog = dialogRef.current; if (!dialog) return; function handleCancel(e: Event) { e.preventDefault(); onClose(); } function handleBackdropClick(e: MouseEvent) { if (e.target === dialog) onClose(); } dialog.addEventListener("cancel", handleCancel); dialog.addEventListener("mousedown", handleBackdropClick); return () => { dialog.removeEventListener("cancel", handleCancel); dialog.removeEventListener("mousedown", handleBackdropClick); }; }, [onClose]); return (

Player Characters

{characters.length === 0 ? (

No player characters yet

) : (
{characters.map((pc) => { const Icon = pc.icon ? PLAYER_ICON_MAP[pc.icon] : undefined; const color = pc.color ? PLAYER_COLOR_HEX[pc.color] : undefined; return (
{!!Icon && ( )} {pc.name} AC {pc.ac} HP {pc.maxHp} } label="Delete player character" onConfirm={() => onDelete(pc.id)} size="icon-sm" className="text-muted-foreground" />
); })}
)}
); }