Add sort options to run team overview
Add a dropdown to sort Active Team and Graveyard by route order, catch level, species name, or national dex number. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { useRun, useUpdateRun } from '../hooks/useRuns'
|
||||
import { useGameRoutes } from '../hooks/useGames'
|
||||
@@ -6,6 +6,28 @@ import { useCreateEncounter, useUpdateEncounter } from '../hooks/useEncounters'
|
||||
import { StatCard, PokemonCard, RuleBadges, StatusChangeModal, EndRunModal } from '../components'
|
||||
import type { RunStatus, EncounterDetail } 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<RunStatus, string> = {
|
||||
active: 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300',
|
||||
completed:
|
||||
@@ -32,6 +54,7 @@ export function RunDashboard() {
|
||||
const [selectedEncounter, setSelectedEncounter] =
|
||||
useState<EncounterDetail | null>(null)
|
||||
const [showEndRun, setShowEndRun] = useState(false)
|
||||
const [teamSort, setTeamSort] = useState<TeamSortKey>('route')
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -58,11 +81,13 @@ export function RunDashboard() {
|
||||
}
|
||||
|
||||
const isActive = run.status === 'active'
|
||||
const alive = run.encounters.filter(
|
||||
(e) => e.status === 'caught' && e.faintLevel === null,
|
||||
const alive = useMemo(
|
||||
() => sortEncounters(run.encounters.filter((e) => e.status === 'caught' && e.faintLevel === null), teamSort),
|
||||
[run.encounters, teamSort],
|
||||
)
|
||||
const dead = run.encounters.filter(
|
||||
(e) => e.status === 'caught' && e.faintLevel !== null,
|
||||
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
|
||||
@@ -172,9 +197,23 @@ export function RunDashboard() {
|
||||
|
||||
{/* Active Team */}
|
||||
<div className="mb-6">
|
||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-3">
|
||||
{isActive ? 'Active Team' : 'Final Team'}
|
||||
</h2>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
|
||||
{isActive ? 'Active Team' : 'Final Team'}
|
||||
</h2>
|
||||
{alive.length > 1 && (
|
||||
<select
|
||||
value={teamSort}
|
||||
onChange={(e) => setTeamSort(e.target.value as TeamSortKey)}
|
||||
className="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-1.5 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
||||
>
|
||||
<option value="route">Route Order</option>
|
||||
<option value="level">Catch Level</option>
|
||||
<option value="species">Species Name</option>
|
||||
<option value="dex">National Dex</option>
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
{alive.length === 0 ? (
|
||||
<p className="text-gray-500 dark:text-gray-400 text-sm">
|
||||
No pokemon caught yet — head to encounters to start building your
|
||||
|
||||
Reference in New Issue
Block a user