Fix run deletion crash and transfer modal initialization error

Run deletion now properly cleans up boss_results, genlocke_transfers,
and genlocke_leg references before deleting the run. Also fix
showTransferModal being referenced before initialization in
RunEncounters by moving its useState declaration above useLegSurvivors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-09 11:28:22 +01:00
parent c5910ec75c
commit e1dac10d27
3 changed files with 35 additions and 4 deletions

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-p74f
title: Genlocke transfer UI
status: in-progress
status: completed
type: feature
priority: normal
created_at: 2026-02-09T07:42:33Z
updated_at: 2026-02-09T10:14:34Z
updated_at: 2026-02-09T10:20:53Z
parent: nuzlocke-tracker-25mh
blocking:
- nuzlocke-tracker-lsc2

View File

@@ -6,9 +6,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload, selectinload
from app.core.database import get_session
from app.models.boss_result import BossResult
from app.models.encounter import Encounter
from app.models.game import Game
from app.models.genlocke import Genlocke, GenlockeLeg
from app.models.genlocke_transfer import GenlockeTransfer
from app.models.nuzlocke_run import NuzlockeRun
from app.schemas.run import RunCreate, RunDetailResponse, RunGenlockeContext, RunResponse, RunUpdate
@@ -198,13 +200,42 @@ async def delete_run(
if run is None:
raise HTTPException(status_code=404, detail="Run not found")
# Delete associated encounters first
# Delete associated boss results first
boss_results = await session.execute(
select(BossResult).where(BossResult.run_id == run_id)
)
for br in boss_results.scalars():
await session.delete(br)
# Delete genlocke transfers referencing this run's encounters
encounter_ids_result = await session.execute(
select(Encounter.id).where(Encounter.run_id == run_id)
)
encounter_ids = [row[0] for row in encounter_ids_result]
if encounter_ids:
transfers = await session.execute(
select(GenlockeTransfer).where(
GenlockeTransfer.source_encounter_id.in_(encounter_ids)
| GenlockeTransfer.target_encounter_id.in_(encounter_ids)
)
)
for t in transfers.scalars():
await session.delete(t)
# Delete associated encounters
encounters = await session.execute(
select(Encounter).where(Encounter.run_id == run_id)
)
for enc in encounters.scalars():
await session.delete(enc)
# Unlink from any genlocke leg
leg_result = await session.execute(
select(GenlockeLeg).where(GenlockeLeg.run_id == run_id)
)
for leg in leg_result.scalars():
leg.run_id = None
await session.delete(run)
await session.commit()
return Response(status_code=204)

View File

@@ -396,6 +396,7 @@ export function RunEncounters() {
const runIdNum = Number(runId)
const { data: run, isLoading, error } = useRun(runIdNum)
const advanceLeg = useAdvanceLeg()
const [showTransferModal, setShowTransferModal] = useState(false)
const { data: survivors } = useLegSurvivors(
run?.genlocke?.genlockeId ?? 0,
run?.genlocke?.legOrder ?? 0,
@@ -423,7 +424,6 @@ export function RunEncounters() {
const [showHofModal, setShowHofModal] = useState(false)
const [showShinyModal, setShowShinyModal] = useState(false)
const [showEggModal, setShowEggModal] = useState(false)
const [showTransferModal, setShowTransferModal] = useState(false)
const [expandedBosses, setExpandedBosses] = useState<Set<number>>(new Set())
const [showTeam, setShowTeam] = useState(true)
const [filter, setFilter] = useState<'all' | RouteStatus>('all')