import { UserPlus } from 'lucide-react'; import type { Snapshot } from '@/lib/sync/messages'; import type { Character } from '@/lib/schemas'; import { Button } from '@/components/ui/Button'; import { EmptyState } from '@/components/ui/Page'; import { Avatar, Badge } from '@/components/ui/Codex'; /** * Shown to a joined player before they control a character: pick "you" from the * party. If a locally-developed copy exists, its offline edits ride along for * the GM to review. */ export function SeatClaimScreen({ snapshot, localChars, ownCharacters = [], pending, onClaim }: { snapshot: Snapshot; localChars: Map; /** the player's own local characters — they can push one the GM hasn't added yet */ ownCharacters?: Character[]; pending: boolean; onClaim: (characterId: string) => void; }) { const partyIds = new Set(snapshot.party.map((p) => p.id)); const pushable = ownCharacters.filter((c) => c.kind === 'pc' && !partyIds.has(c.id)); if (snapshot.party.length === 0 && pushable.length === 0) { return ; } return (
Claim your seat

Which character is yours?

Pick your character to manage its HP, spells, and rolls live. The GM approves the request.


{snapshot.party.length > 0 && (
{snapshot.party.map((c) => { const hasOffline = localChars.has(c.id); return (
{c.name}
Lv {c.level} · AC {c.ac} · {c.hp.current}/{c.hp.max} HP
{hasOffline && offline edits ready}
); })}
)} {pushable.length > 0 && (

Bring your own character

{pushable.map((c) => (
{c.name}
Lv {c.level}{c.className ? ` · ${c.className}` : ''}
send to the GM
))}
)} {pending &&

Waiting for the GM to approve…

}
); }