'use client'; import { useState } from 'react'; import type { Action } from '@/game/engine'; import { leaderSkillCard, type LeaderSkillId } from '@/game/leader-skill-cards'; import type { LeaderSkillsView } from '@/game/leader-skills'; import { Button } from '@/components/ui/button'; type NamedIdentity = Readonly<{ id: string; name: string }>; export type LeaderSkillsPanelProps = { skills: LeaderSkillsView | null; leaders: readonly NamedIdentity[]; players: readonly NamedIdentity[]; act: (action: Action) => void; busy: boolean; }; function LeaderSkillCard({ skill, context, }: { skill: LeaderSkillId; context?: string; }) { const card = leaderSkillCard(skill); return (

Leader Skill

{card.name}

{context && (

{context}

)}
Inspect {card.name}
Normal effect
{card.normal.map((line) => (

{line}

))}
Skilled leader in battle
{card.battle.map((line) => (

{line}

))}
); } export function LeaderSkillsPanel({ skills, leaders, players, act, busy, }: LeaderSkillsPanelProps) { const [selectedSkill, setSelectedSkill] = useState( null, ); const [selectedLeader, setSelectedLeader] = useState(null); if (!skills) return null; const offer = skills.offer; const availableSkills = offer?.cards.filter((skill) => !skills.unavailableSkills?.[skill]) ?? []; const activeSkill = availableSkills.find((skill) => skill === selectedSkill) ?? availableSkills[0] ?? null; const activeLeader = offer?.leader ?? skills.eligibleLeaders.find((leader) => leader.id === selectedLeader)?.id ?? skills.eligibleLeaders[0]?.id ?? null; const leaderName = (id: string) => leaders.find((leader) => leader.id === id)?.name ?? id; const playerName = (id: string) => players.find((player) => player.id === id)?.name ?? id; return (

Leader Skills

This development-only module currently connects the card-role strength modifiers for Warmaster, Master of Assassins, Swordmaster of Ginaz, Killer Medic and Prana-Bindu Adept, plus Planetologist movement and Special-card battle use, Suk Graduate force rescue, Mentat’s private weapon question and battle bonus, Bureaucrat payment redirection and battle scores, Sandmaster ground-route collection and victory spice, Rihani inspections and exchanges, optional Smuggler reserve shipping and provisional modifier-inclusive battle collection, mandatory deferred Spice Banker income in fresh setups, separate Banker battle spending, and Diplomat copying an opposing canonical printed defensive role with a committed Worthless card after plans are revealed. Source-specific timing and combinations remain guarded; complete mode acceptance is unfinished.

{!!skills.assignments.length && (

Public assignments

{skills.assignments.map((assignment) => ( ))}
)} {offer && offer.cards.length === 0 && offer.leader && (

Skill for {leaderName(offer.leader)}

Decide whether to draw before seeing either private card. Drawing two requires you to keep one.

)} {offer && offer.cards.length > 0 && (
{ event.preventDefault(); if (!busy && activeSkill && activeLeader) act({ type: 'leaderSkill', event: offer.event, skill: activeSkill, leader: activeLeader, }); }} >

Choose one private skill

Keep one physical card and return the other unseen card to the skill deck.

Choose a skill card
{offer.cards.map((skill) => { const card = leaderSkillCard(skill); const unavailable = skills.unavailableSkills?.[skill]; return (
{unavailable &&

{unavailable}

}
); })}
{offer.leader ? (

Assigned leader: {leaderName(offer.leader)}

) : ( )}

Once these cards are shown, choosing one is mandatory; there is no decline action.

)} {skills.battleChoice && (

{leaderName(skills.battleChoice.leader)} in this battle

Choose publicly whether the skilled leader remains face up or moves behind your shield before selecting a Battle Plan leader.

)}
); }