import type { PlayerCharacter } from "@initiative/domain"; import { X } from "lucide-react"; import { useEffect, useState } from "react"; import { ColorPalette } from "./color-palette"; import { IconGrid } from "./icon-grid"; import { Button } from "./ui/button"; import { Dialog } from "./ui/dialog"; import { Input } from "./ui/input"; function parseLevel(value: string): number | undefined | "invalid" { if (value.trim() === "") return undefined; const n = Number.parseInt(value, 10); if (Number.isNaN(n) || n < 1 || n > 20) return "invalid"; return n; } interface CreatePlayerModalProps { open: boolean; onClose: () => void; onSave: ( name: string, ac: number, maxHp: number, color: string | undefined, icon: string | undefined, level: number | undefined, ) => void; playerCharacter?: PlayerCharacter; } export function CreatePlayerModal({ open, onClose, onSave, playerCharacter, }: Readonly) { const [name, setName] = useState(""); const [ac, setAc] = useState("10"); const [maxHp, setMaxHp] = useState("10"); const [color, setColor] = useState("blue"); const [icon, setIcon] = useState("sword"); const [level, setLevel] = useState(""); const [error, setError] = useState(""); const isEdit = !!playerCharacter; useEffect(() => { if (open) { if (playerCharacter) { setName(playerCharacter.name); setAc(String(playerCharacter.ac)); setMaxHp(String(playerCharacter.maxHp)); setColor(playerCharacter.color ?? ""); setIcon(playerCharacter.icon ?? ""); setLevel( playerCharacter.level === undefined ? "" : String(playerCharacter.level), ); } else { setName(""); setAc("10"); setMaxHp("10"); setColor(""); setIcon(""); setLevel(""); } setError(""); } }, [open, playerCharacter]); const handleSubmit = (e: React.SubmitEvent) => { e.preventDefault(); const trimmed = name.trim(); if (trimmed === "") { setError("Name is required"); return; } const acNum = Number.parseInt(ac, 10); if (Number.isNaN(acNum) || acNum < 0) { setError("AC must be a non-negative number"); return; } const hpNum = Number.parseInt(maxHp, 10); if (Number.isNaN(hpNum) || hpNum < 1) { setError("Max HP must be at least 1"); return; } const levelNum = parseLevel(level); if (levelNum === "invalid") { setError("Level must be between 1 and 20"); return; } onSave( trimmed, acNum, hpNum, color || undefined, icon || undefined, levelNum, ); onClose(); }; return (

{isEdit ? "Edit Player" : "Create Player"}

Name { setName(e.target.value); setError(""); }} placeholder="Character name" aria-label="Name" autoFocus /> {!!error &&

{error}

}
AC setAc(e.target.value)} placeholder="AC" aria-label="AC" className="text-center" />
Max HP setMaxHp(e.target.value)} placeholder="Max HP" aria-label="Max HP" className="text-center" />
Level setLevel(e.target.value)} placeholder="1-20" aria-label="Level" className="text-center" />
Color
Icon
); }