import { useState, useMemo } from 'react' import { AdminTable, type Column } from '../../components/admin/AdminTable' import { DeleteConfirmModal } from '../../components/admin/DeleteConfirmModal' import { useRuns, useDeleteRun } from '../../hooks/useRuns' import { useGames } from '../../hooks/useGames' import type { NuzlockeRun } from '../../types/game' export function AdminRuns() { const { data: runs = [], isLoading: runsLoading } = useRuns() const { data: games = [], isLoading: gamesLoading } = useGames() const deleteRun = useDeleteRun() const [deleting, setDeleting] = useState(null) const [statusFilter, setStatusFilter] = useState('') const [gameFilter, setGameFilter] = useState('') const [ownerFilter, setOwnerFilter] = useState('') const gameMap = useMemo(() => new Map(games.map((g) => [g.id, g.name])), [games]) const filteredRuns = useMemo(() => { let result = runs if (statusFilter) result = result.filter((r) => r.status === statusFilter) if (gameFilter) result = result.filter((r) => r.gameId === Number(gameFilter)) if (ownerFilter) { if (ownerFilter === '__none__') { result = result.filter((r) => !r.owner) } else { result = result.filter((r) => r.owner?.id === ownerFilter) } } return result }, [runs, statusFilter, gameFilter, ownerFilter]) const runGames = useMemo( () => [ ...new Map( runs.map((r) => [r.gameId, gameMap.get(r.gameId) ?? `Game #${r.gameId}`]) ).entries(), ].sort((a, b) => a[1].localeCompare(b[1])), [runs, gameMap] ) const runOwners = useMemo(() => { const owners = new Map() let hasUnowned = false for (const r of runs) { if (r.owner) { owners.set(r.owner.id, r.owner.displayName ?? r.owner.id) } else { hasUnowned = true } } const sorted = [...owners.entries()].sort((a, b) => a[1].localeCompare(b[1])) return { owners: sorted, hasUnowned } }, [runs]) const columns: Column[] = [ { header: 'Run Name', accessor: (r) => r.name, sortKey: (r) => r.name }, { header: 'Game', accessor: (r) => gameMap.get(r.gameId) ?? `Game #${r.gameId}`, sortKey: (r) => gameMap.get(r.gameId) ?? '', }, { header: 'Owner', accessor: (r) => ( {r.owner?.displayName ?? r.owner?.id ?? 'No owner'} ), sortKey: (r) => r.owner?.displayName ?? r.owner?.id ?? '', }, { header: 'Status', accessor: (r) => ( {r.status} ), sortKey: (r) => r.status, }, { header: 'Started', accessor: (r) => new Date(r.startedAt).toLocaleDateString(), sortKey: (r) => r.startedAt, }, ] return (

Runs

{(statusFilter || gameFilter || ownerFilter) && ( )} {filteredRuns.length} runs
r.id} onRowClick={(r) => setDeleting(r)} /> {deleting && ( deleteRun.mutate(deleting.id, { onSuccess: () => setDeleting(null), }) } onCancel={() => { setDeleting(null) deleteRun.reset() }} isDeleting={deleteRun.isPending} error={deleteRun.error?.message ?? null} /> )}
) }