Add conditional boss battle teams (variant teams by condition)
Wire up the existing condition_label column on boss_pokemon to support variant teams throughout the UI. Boss battles can now have multiple team configurations based on conditions (e.g., starter choice in Gen 1). - Add condition_label to BossPokemonInput schema (frontend + backend bulk import) - Rewrite BossTeamEditor with variant tabs (Default + named conditions) - Add variant pill selector to BossDefeatModal team preview - Add BossTeamPreview component to RunEncounters boss cards - Fix MissingGreenlet error in set_boss_team via session.expunge_all() - Fix PokemonSelector state bleed between tabs via composite React key - Add Alembic migration for condition_label column Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
"""add condition_label to boss_pokemon
|
||||
|
||||
Revision ID: b7c8d9e0f1a2
|
||||
Revises: a6b7c8d9e0f1
|
||||
Create Date: 2026-02-08 22:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'b7c8d9e0f1a2'
|
||||
down_revision: Union[str, Sequence[str], None] = 'a6b7c8d9e0f1'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column('boss_pokemon', sa.Column('condition_label', sa.String(100), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column('boss_pokemon', 'condition_label')
|
||||
@@ -228,11 +228,17 @@ async def set_boss_team(
|
||||
pokemon_id=item.pokemon_id,
|
||||
level=item.level,
|
||||
order=item.order,
|
||||
condition_label=item.condition_label,
|
||||
)
|
||||
session.add(bp)
|
||||
|
||||
await session.commit()
|
||||
|
||||
# Clear identity map so selectinload fetches everything fresh
|
||||
# (expired Pokemon from deleted BossPokemon would otherwise cause
|
||||
# MissingGreenlet errors during response serialization)
|
||||
session.expunge_all()
|
||||
|
||||
# Re-fetch with eager loading
|
||||
result = await session.execute(
|
||||
select(BossBattle)
|
||||
|
||||
@@ -154,6 +154,7 @@ async def export_game_bosses(
|
||||
"pokemon_name": bp.pokemon.name,
|
||||
"level": bp.level,
|
||||
"order": bp.order,
|
||||
**({"condition_label": bp.condition_label} if bp.condition_label else {}),
|
||||
}
|
||||
for bp in sorted(b.pokemon, key=lambda p: p.order)
|
||||
],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from sqlalchemy import ForeignKey, SmallInteger
|
||||
from sqlalchemy import ForeignKey, SmallInteger, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.core.database import Base
|
||||
@@ -14,6 +14,7 @@ class BossPokemon(Base):
|
||||
pokemon_id: Mapped[int] = mapped_column(ForeignKey("pokemon.id"), index=True)
|
||||
level: Mapped[int] = mapped_column(SmallInteger)
|
||||
order: Mapped[int] = mapped_column(SmallInteger)
|
||||
condition_label: Mapped[str | None] = mapped_column(String(100))
|
||||
|
||||
boss_battle: Mapped["BossBattle"] = relationship(back_populates="pokemon")
|
||||
pokemon: Mapped["Pokemon"] = relationship()
|
||||
|
||||
@@ -9,6 +9,7 @@ class BossPokemonResponse(CamelModel):
|
||||
pokemon_id: int
|
||||
level: int
|
||||
order: int
|
||||
condition_label: str | None
|
||||
pokemon: PokemonResponse
|
||||
|
||||
|
||||
@@ -73,6 +74,7 @@ class BossPokemonInput(CamelModel):
|
||||
pokemon_id: int
|
||||
level: int
|
||||
order: int
|
||||
condition_label: str | None = None
|
||||
|
||||
|
||||
class BossResultCreate(CamelModel):
|
||||
|
||||
@@ -200,6 +200,7 @@ class BulkBossPokemonItem(BaseModel):
|
||||
pokeapi_id: int
|
||||
level: int
|
||||
order: int
|
||||
condition_label: str | None = None
|
||||
|
||||
|
||||
class BulkBossItem(BaseModel):
|
||||
|
||||
@@ -270,6 +270,7 @@ async def upsert_bosses(
|
||||
pokemon_id=pokemon_id,
|
||||
level=bp["level"],
|
||||
order=bp["order"],
|
||||
condition_label=bp.get("condition_label"),
|
||||
))
|
||||
|
||||
count += 1
|
||||
|
||||
Reference in New Issue
Block a user