Files
nuzlocke-tracker/backend/src/app/schemas/pokemon.py
Julian Tabel a6bf8b4af2 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>
2026-02-08 21:20:30 +01:00

219 lines
4.5 KiB
Python

from pydantic import BaseModel
from app.schemas.base import CamelModel
class PokemonResponse(CamelModel):
id: int
pokeapi_id: int
national_dex: int
name: str
types: list[str]
sprite_url: str | None
class PaginatedPokemonResponse(CamelModel):
items: list[PokemonResponse]
total: int
limit: int
offset: int
class EvolutionResponse(CamelModel):
id: int
from_pokemon_id: int
to_pokemon: PokemonResponse
trigger: str
min_level: int | None
item: str | None
held_item: str | None
condition: str | None
region: str | None
class FamiliesResponse(CamelModel):
families: list[list[int]]
class RouteEncounterResponse(CamelModel):
id: int
route_id: int
pokemon_id: int
game_id: int
encounter_method: str
encounter_rate: int
min_level: int
max_level: int
class RouteEncounterDetailResponse(RouteEncounterResponse):
pokemon: PokemonResponse
class PokemonEncounterLocationItem(CamelModel):
route_id: int
route_name: str
encounter_method: str
encounter_rate: int
min_level: int
max_level: int
class PokemonEncounterLocationResponse(CamelModel):
game_id: int
game_name: str
encounters: list[PokemonEncounterLocationItem]
# --- Admin schemas ---
class PokemonCreate(CamelModel):
pokeapi_id: int
national_dex: int
name: str
types: list[str]
sprite_url: str | None = None
class PokemonUpdate(CamelModel):
pokeapi_id: int | None = None
national_dex: int | None = None
name: str | None = None
types: list[str] | None = None
sprite_url: str | None = None
class RouteEncounterCreate(CamelModel):
pokemon_id: int
game_id: int
encounter_method: str
encounter_rate: int
min_level: int
max_level: int
class RouteEncounterUpdate(CamelModel):
encounter_method: str | None = None
encounter_rate: int | None = None
min_level: int | None = None
max_level: int | None = None
class BulkImportItem(BaseModel):
pokeapi_id: int
national_dex: int
name: str
types: list[str]
sprite_url: str | None = None
class BulkImportResult(CamelModel):
created: int
updated: int
errors: list[str]
# --- Evolution admin schemas ---
class EvolutionAdminResponse(CamelModel):
id: int
from_pokemon_id: int
to_pokemon_id: int
from_pokemon: PokemonResponse
to_pokemon: PokemonResponse
trigger: str
min_level: int | None
item: str | None
held_item: str | None
condition: str | None
region: str | None
class PaginatedEvolutionResponse(CamelModel):
items: list[EvolutionAdminResponse]
total: int
limit: int
offset: int
class EvolutionCreate(CamelModel):
from_pokemon_id: int
to_pokemon_id: int
trigger: str
min_level: int | None = None
item: str | None = None
held_item: str | None = None
condition: str | None = None
region: str | None = None
class EvolutionUpdate(CamelModel):
from_pokemon_id: int | None = None
to_pokemon_id: int | None = None
trigger: str | None = None
min_level: int | None = None
item: str | None = None
held_item: str | None = None
condition: str | None = None
region: str | None = None
# --- Bulk import schemas (match export format, snake_case) ---
class BulkEvolutionItem(BaseModel):
from_pokeapi_id: int
to_pokeapi_id: int
trigger: str
min_level: int | None = None
item: str | None = None
held_item: str | None = None
condition: str | None = None
region: str | None = None
class BulkRouteEncounterItem(BaseModel):
pokeapi_id: int
method: str
encounter_rate: int
min_level: int
max_level: int
class BulkRouteChildItem(BaseModel):
name: str
order: int
pinwheel_zone: int | None = None
encounters: list[BulkRouteEncounterItem] = []
class BulkRouteItem(BaseModel):
name: str
order: int
encounters: list[BulkRouteEncounterItem] = []
children: list[BulkRouteChildItem] = []
class BulkBossPokemonItem(BaseModel):
pokeapi_id: int
level: int
order: int
condition_label: str | None = None
class BulkBossItem(BaseModel):
name: str
boss_type: str
specialty_type: str | None = None
badge_name: str | None = None
badge_image_url: str | None = None
level_cap: int
order: int
after_route_name: str | None = None
location: str
section: str | None = None
sprite_url: str | None = None
pokemon: list[BulkBossPokemonItem] = []