import { type FormEvent, useMemo, useState } from 'react' import type { BossBattle, BossResultTeamMemberInput, CreateBossResultInput, EncounterDetail, } from '../types/game' import { ConditionBadge } from './ConditionBadge' interface BossDefeatModalProps { boss: BossBattle aliveEncounters: EncounterDetail[] onSubmit: (data: CreateBossResultInput) => void onClose: () => void isPending?: boolean starterName?: string | null } function matchVariant(labels: string[], starterName?: string | null): string | null { if (!starterName || labels.length === 0) return null const lower = starterName.toLowerCase() const matches = labels.filter((l) => l.toLowerCase().includes(lower)) return matches.length === 1 ? (matches[0] ?? null) : null } type TeamSelection = number export function BossDefeatModal({ boss, aliveEncounters, onSubmit, onClose, isPending, starterName, }: BossDefeatModalProps) { const [selectedTeam, setSelectedTeam] = useState>(new Set()) const toggleTeamMember = (encounterId: number) => { setSelectedTeam((prev) => { const next = new Set(prev) if (next.has(encounterId)) { next.delete(encounterId) } else { next.add(encounterId) } return next }) } const variantLabels = useMemo(() => { const labels = new Set() for (const bp of boss.pokemon) { if (bp.conditionLabel) labels.add(bp.conditionLabel) } return [...labels].sort() }, [boss.pokemon]) const hasVariants = variantLabels.length > 0 const autoMatch = useMemo( () => matchVariant(variantLabels, starterName), [variantLabels, starterName] ) const showPills = hasVariants && autoMatch === null const [selectedVariant, setSelectedVariant] = useState( autoMatch ?? (hasVariants ? (variantLabels[0] ?? null) : null) ) const displayedPokemon = useMemo(() => { if (!hasVariants) return boss.pokemon return boss.pokemon.filter( (bp) => bp.conditionLabel === selectedVariant || bp.conditionLabel === null ) }, [boss.pokemon, hasVariants, selectedVariant]) const handleSubmit = (e: FormEvent) => { e.preventDefault() const team: BossResultTeamMemberInput[] = Array.from(selectedTeam).map((encounterId) => ({ encounterId, })) onSubmit({ bossBattleId: boss.id, result: 'won', attempts: 1, team, }) } return (

Battle: {boss.name}

{boss.location}

{/* Boss team preview */} {boss.pokemon.length > 0 && (
{showPills && (
{variantLabels.map((label) => ( ))}
)}
{[...displayedPokemon] .sort((a, b) => a.order - b.order) .map((bp) => { const moves = [bp.move1, bp.move2, bp.move3, bp.move4].filter(Boolean) return (
{bp.pokemon.spriteUrl ? ( {bp.pokemon.name} ) : (
)} {bp.pokemon.name} Lv.{bp.level} {bp.ability && ( {bp.ability.name} )} {bp.heldItem && ( {bp.heldItem} )} {moves.length > 0 && (
{moves.map((m) => m!.name).join(', ')}
)}
) })}
)} {/* Team selection */} {aliveEncounters.length > 0 && (

Your team (optional)

{aliveEncounters.map((enc) => { const isSelected = selectedTeam.has(enc.id) const displayPokemon = enc.currentPokemon ?? enc.pokemon return (
toggleTeamMember(enc.id)} > toggleTeamMember(enc.id)} className="sr-only" /> {displayPokemon.spriteUrl ? ( {displayPokemon.name} ) : (
)}

{enc.nickname ?? displayPokemon.name}

) })}
)}
) }