diff --git a/frontend/src/pages/RunDashboard.tsx b/frontend/src/pages/RunDashboard.tsx index 2d5472f..fcda00b 100644 --- a/frontend/src/pages/RunDashboard.tsx +++ b/frontend/src/pages/RunDashboard.tsx @@ -56,6 +56,16 @@ export function RunDashboard() { const [showEndRun, setShowEndRun] = useState(false) const [teamSort, setTeamSort] = useState('route') + const encounters = run?.encounters ?? [] + const alive = useMemo( + () => sortEncounters(encounters.filter((e) => e.status === 'caught' && e.faintLevel === null), teamSort), + [encounters, teamSort], + ) + const dead = useMemo( + () => sortEncounters(encounters.filter((e) => e.status === 'caught' && e.faintLevel !== null), teamSort), + [encounters, teamSort], + ) + if (isLoading) { return (
@@ -81,14 +91,6 @@ export function RunDashboard() { } const isActive = run.status === 'active' - const alive = useMemo( - () => sortEncounters(run.encounters.filter((e) => e.status === 'caught' && e.faintLevel === null), teamSort), - [run.encounters, teamSort], - ) - const dead = useMemo( - () => sortEncounters(run.encounters.filter((e) => e.status === 'caught' && e.faintLevel !== null), teamSort), - [run.encounters, teamSort], - ) const visitedRoutes = new Set(run.encounters.map((e) => e.routeId)).size const totalRoutes = routes?.length diff --git a/frontend/src/pages/RunEncounters.tsx b/frontend/src/pages/RunEncounters.tsx index fa9e324..ec50e65 100644 --- a/frontend/src/pages/RunEncounters.tsx +++ b/frontend/src/pages/RunEncounters.tsx @@ -33,6 +33,28 @@ import type { BossPokemon, } from '../types' +type TeamSortKey = 'route' | 'level' | 'species' | 'dex' + +function sortEncounters(encounters: EncounterDetail[], key: TeamSortKey): EncounterDetail[] { + return [...encounters].sort((a, b) => { + switch (key) { + case 'route': + return a.route.order - b.route.order + case 'level': + return (a.catchLevel ?? 0) - (b.catchLevel ?? 0) + case 'species': { + const nameA = (a.currentPokemon ?? a.pokemon).name + const nameB = (b.currentPokemon ?? b.pokemon).name + return nameA.localeCompare(nameB) + } + case 'dex': + return (a.currentPokemon ?? a.pokemon).nationalDex - (b.currentPokemon ?? b.pokemon).nationalDex + default: + return 0 + } + }) +} + const statusStyles: Record = { active: 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300', completed: @@ -421,6 +443,7 @@ export function RunEncounters() { const [showEggModal, setShowEggModal] = useState(false) const [expandedBosses, setExpandedBosses] = useState>(new Set()) const [showTeam, setShowTeam] = useState(true) + const [teamSort, setTeamSort] = useState('route') const [filter, setFilter] = useState<'all' | RouteStatus>('all') const storageKey = `expandedGroups-${runId}` @@ -621,10 +644,21 @@ export function RunEncounters() { }, [organizedRoutes, encounterByRoute]) // eslint-disable-line react-hooks/exhaustive-deps const alive = useMemo( - () => [...normalEncounters, ...transferEncounters, ...shinyEncounters].filter( - (e) => e.status === 'caught' && e.faintLevel === null, + () => sortEncounters( + [...normalEncounters, ...transferEncounters, ...shinyEncounters].filter( + (e) => e.status === 'caught' && e.faintLevel === null, + ), + teamSort, ), - [normalEncounters, transferEncounters, shinyEncounters], + [normalEncounters, transferEncounters, shinyEncounters, teamSort], + ) + + const dead = useMemo( + () => sortEncounters( + normalEncounters.filter((e) => e.status === 'caught' && e.faintLevel !== null), + teamSort, + ), + [normalEncounters, teamSort], ) // Resolve HoF team encounters from IDs @@ -686,9 +720,6 @@ export function RunEncounters() { } const isActive = run.status === 'active' - const dead = normalEncounters.filter( - (e) => e.status === 'caught' && e.faintLevel !== null, - ) const toggleGroup = (groupId: number) => { updateExpandedGroups((prev) => { @@ -1036,31 +1067,45 @@ export function RunEncounters() { {/* Team Section */} {(alive.length > 0 || dead.length > 0) && (
- +

+ {isActive ? 'Team' : 'Final Team'} +

+ + {alive.length} alive{dead.length > 0 ? `, ${dead.length} dead` : ''} + + + + + + {showTeam && alive.length > 1 && ( + + )} +
{showTeam && ( <> {alive.length > 0 && (