diff --git a/backend/src/app/api/encounters.py b/backend/src/app/api/encounters.py index 4107734..b0d1668 100644 --- a/backend/src/app/api/encounters.py +++ b/backend/src/app/api/encounters.py @@ -8,6 +8,7 @@ from sqlalchemy.orm import joinedload, selectinload from app.core.database import get_session from app.models.encounter import Encounter from app.models.evolution import Evolution +from app.models.genlocke_transfer import GenlockeTransfer from app.models.genlocke import GenlockeLeg from app.models.nuzlocke_run import NuzlockeRun from app.models.pokemon import Pokemon @@ -85,11 +86,14 @@ async def create_encounter( sibling_ids = [s.id for s in siblings] # Check if any relevant sibling already has an encounter in this run + # Exclude transfer-target encounters so they don't block the starter + transfer_target_ids = select(GenlockeTransfer.target_encounter_id) existing_encounter = await session.execute( select(Encounter) .where( Encounter.run_id == run_id, Encounter.route_id.in_(sibling_ids), + ~Encounter.id.in_(transfer_target_ids), ) ) if existing_encounter.scalar_one_or_none() is not None: diff --git a/backend/src/app/api/runs.py b/backend/src/app/api/runs.py index 293740e..2947c65 100644 --- a/backend/src/app/api/runs.py +++ b/backend/src/app/api/runs.py @@ -105,8 +105,19 @@ async def get_run(run_id: int, session: AsyncSession = Depends(get_session)): retired_pokemon_ids=retired_pokemon_ids, ) + # Load transfer-target encounter IDs for this run + transfer_ids_result = await session.execute( + select(GenlockeTransfer.target_encounter_id).where( + GenlockeTransfer.target_encounter_id.in_( + select(Encounter.id).where(Encounter.run_id == run_id) + ) + ) + ) + transfer_encounter_ids = [row[0] for row in transfer_ids_result] + response = RunDetailResponse.model_validate(run) response.genlocke = genlocke_context + response.transfer_encounter_ids = transfer_encounter_ids return response diff --git a/backend/src/app/schemas/run.py b/backend/src/app/schemas/run.py index 13b7c64..32f7431 100644 --- a/backend/src/app/schemas/run.py +++ b/backend/src/app/schemas/run.py @@ -42,3 +42,4 @@ class RunDetailResponse(RunResponse): game: GameResponse encounters: list[EncounterDetailResponse] = [] genlocke: RunGenlockeContext | None = None + transfer_encounter_ids: list[int] = [] diff --git a/frontend/src/components/TransferModal.tsx b/frontend/src/components/TransferModal.tsx index e0ea836..f9daa02 100644 --- a/frontend/src/components/TransferModal.tsx +++ b/frontend/src/components/TransferModal.tsx @@ -1,16 +1,16 @@ import { useState } from 'react' -import type { SurvivorEncounter } from '../types' +import type { EncounterDetail } from '../types' interface TransferModalProps { - survivors: SurvivorEncounter[] + hofTeam: EncounterDetail[] onSubmit: (encounterIds: number[]) => void onSkip: () => void isPending: boolean } -export function TransferModal({ survivors, onSubmit, onSkip, isPending }: TransferModalProps) { +export function TransferModal({ hofTeam, onSubmit, onSkip, isPending }: TransferModalProps) { const [selected, setSelected] = useState>( - () => new Set(survivors.map((s) => s.id)), + () => new Set(hofTeam.map((e) => e.id)), ) const toggle = (id: number) => { @@ -39,54 +39,48 @@ export function TransferModal({ survivors, onSubmit, onSkip, isPending }: Transf
- {survivors.length === 0 ? ( -

- No surviving Pokemon to transfer. -

- ) : ( -
- {survivors.map((survivor) => { - const displayPokemon = survivor.currentPokemon ?? survivor.pokemon - const isSelected = selected.has(survivor.id) +
+ {hofTeam.map((enc) => { + const displayPokemon = enc.currentPokemon ?? enc.pokemon + const isSelected = selected.has(enc.id) - return ( - - ) - })} -
- )} + )} + + {enc.route.name} + + + ) + })} +
@@ -100,7 +94,7 @@ export function TransferModal({ survivors, onSubmit, onSkip, isPending }: Transf
- {selected.size}/{survivors.length} selected + {selected.size}/{hofTeam.length} selected
{run.status === 'completed' && run.genlocke && !run.genlocke.isFinalLeg && (
)} + {/* Transfer Encounters */} + {transferEncounters.length > 0 && ( +
+

+ Transferred Pokemon +

+
+ {transferEncounters.map((enc) => ( + setSelectedTeamEncounter(enc) : undefined} + /> + ))} +
+
+ )} + {/* Progress bar */}
@@ -1449,9 +1488,9 @@ export function RunEncounters() { )} {/* Transfer Modal */} - {showTransferModal && survivors && ( + {showTransferModal && hofTeam && hofTeam.length > 0 && ( { advanceLeg.mutate( { diff --git a/frontend/src/types/game.ts b/frontend/src/types/game.ts index f835285..e1a1bd1 100644 --- a/frontend/src/types/game.ts +++ b/frontend/src/types/game.ts @@ -107,6 +107,7 @@ export interface RunDetail extends NuzlockeRun { game: Game encounters: EncounterDetail[] genlocke: RunGenlockeContext | null + transferEncounterIds: number[] } export interface EncounterDetail extends Encounter {