Add drag-and-drop boss reordering and new feature beans

Adds boss battle reorder API endpoint with two-phase order update to
avoid unique constraint violations. Includes frontend mutation hook
and API client. Also adds draft beans for progression dividers and
conditional boss battle teams features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 14:58:49 +01:00
parent a4f814e66e
commit 1bf37a6bd9
6 changed files with 119 additions and 2 deletions

View File

@@ -16,6 +16,7 @@ from app.schemas.boss import (
BossBattleResponse,
BossBattleUpdate,
BossPokemonInput,
BossReorderRequest,
BossResultCreate,
BossResultResponse,
)
@@ -50,6 +51,45 @@ async def list_bosses(
return result.scalars().all()
@router.put("/games/{game_id}/bosses/reorder", response_model=list[BossBattleResponse])
async def reorder_bosses(
game_id: int,
data: BossReorderRequest,
session: AsyncSession = Depends(get_session),
):
vg_id = await _get_version_group_id(session, game_id)
boss_ids = [item.id for item in data.bosses]
result = await session.execute(
select(BossBattle).where(
BossBattle.id.in_(boss_ids), BossBattle.version_group_id == vg_id
)
)
bosses = {b.id: b for b in result.scalars().all()}
if len(bosses) != len(boss_ids):
raise HTTPException(status_code=400, detail="Some boss IDs not found in this game")
# Phase 1: set temporary negative orders to avoid unique constraint violations
for i, item in enumerate(data.bosses):
bosses[item.id].order = -(i + 1)
await session.flush()
# Phase 2: set real orders
for item in data.bosses:
bosses[item.id].order = item.order
await session.commit()
# Re-fetch with eager loading
result = await session.execute(
select(BossBattle)
.where(BossBattle.version_group_id == vg_id)
.options(selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon))
.order_by(BossBattle.order)
)
return result.scalars().all()
@router.post("/games/{game_id}/bosses", response_model=BossBattleResponse, status_code=201)
async def create_boss(
game_id: int,