Files
nuzlocke-tracker/frontend/src/api/admin.ts
Julian Tabel 5d54c00af0 Add tabbed UI for routes/bosses and boss export endpoint
Refactors AdminGameDetail to use tabs instead of stacked sections,
adds GET /export/games/{game_id}/bosses endpoint, and adds Export
button to the Boss Battles tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:52:18 +01:00

128 lines
4.3 KiB
TypeScript

import { api } from './client'
import type {
Game,
Route,
Pokemon,
RouteEncounterDetail,
BossBattle,
CreateGameInput,
UpdateGameInput,
CreateRouteInput,
UpdateRouteInput,
RouteReorderItem,
CreatePokemonInput,
UpdatePokemonInput,
BulkImportResult,
PaginatedPokemon,
CreateRouteEncounterInput,
UpdateRouteEncounterInput,
EvolutionAdmin,
PaginatedEvolutions,
CreateEvolutionInput,
UpdateEvolutionInput,
CreateBossBattleInput,
UpdateBossBattleInput,
BossPokemonInput,
} from '../types'
// Games
export const createGame = (data: CreateGameInput) =>
api.post<Game>('/games', data)
export const updateGame = (id: number, data: UpdateGameInput) =>
api.put<Game>(`/games/${id}`, data)
export const deleteGame = (id: number) =>
api.del(`/games/${id}`)
// Routes
export const createRoute = (gameId: number, data: CreateRouteInput) =>
api.post<Route>(`/games/${gameId}/routes`, data)
export const updateRoute = (gameId: number, routeId: number, data: UpdateRouteInput) =>
api.put<Route>(`/games/${gameId}/routes/${routeId}`, data)
export const deleteRoute = (gameId: number, routeId: number) =>
api.del(`/games/${gameId}/routes/${routeId}`)
export const reorderRoutes = (gameId: number, routes: RouteReorderItem[]) =>
api.put<Route[]>(`/games/${gameId}/routes/reorder`, { routes })
// Pokemon
export const listPokemon = (search?: string, limit = 50, offset = 0) => {
const params = new URLSearchParams()
if (search) params.set('search', search)
params.set('limit', String(limit))
params.set('offset', String(offset))
return api.get<PaginatedPokemon>(`/pokemon?${params}`)
}
export const createPokemon = (data: CreatePokemonInput) =>
api.post<Pokemon>('/pokemon', data)
export const updatePokemon = (id: number, data: UpdatePokemonInput) =>
api.put<Pokemon>(`/pokemon/${id}`, data)
export const deletePokemon = (id: number) =>
api.del(`/pokemon/${id}`)
export const bulkImportPokemon = (items: Array<{ pokeapiId: number; nationalDex: number; name: string; types: string[]; spriteUrl?: string | null }>) =>
api.post<BulkImportResult>('/pokemon/bulk-import', items)
// Evolutions
export const listEvolutions = (search?: string, limit = 50, offset = 0) => {
const params = new URLSearchParams()
if (search) params.set('search', search)
params.set('limit', String(limit))
params.set('offset', String(offset))
return api.get<PaginatedEvolutions>(`/evolutions?${params}`)
}
export const createEvolution = (data: CreateEvolutionInput) =>
api.post<EvolutionAdmin>('/evolutions', data)
export const updateEvolution = (id: number, data: UpdateEvolutionInput) =>
api.put<EvolutionAdmin>(`/evolutions/${id}`, data)
export const deleteEvolution = (id: number) =>
api.del(`/evolutions/${id}`)
// Export
export const exportGames = () =>
api.get<Record<string, unknown>[]>('/export/games')
export const exportGameRoutes = (gameId: number) =>
api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/routes`)
export const exportGameBosses = (gameId: number) =>
api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/bosses`)
export const exportPokemon = () =>
api.get<Record<string, unknown>[]>('/export/pokemon')
export const exportEvolutions = () =>
api.get<Record<string, unknown>[]>('/export/evolutions')
// Route Encounters
export const addRouteEncounter = (routeId: number, data: CreateRouteEncounterInput) =>
api.post<RouteEncounterDetail>(`/routes/${routeId}/pokemon`, data)
export const updateRouteEncounter = (routeId: number, encounterId: number, data: UpdateRouteEncounterInput) =>
api.put<RouteEncounterDetail>(`/routes/${routeId}/pokemon/${encounterId}`, data)
export const removeRouteEncounter = (routeId: number, encounterId: number) =>
api.del(`/routes/${routeId}/pokemon/${encounterId}`)
// Boss Battles
export const createBossBattle = (gameId: number, data: CreateBossBattleInput) =>
api.post<BossBattle>(`/games/${gameId}/bosses`, data)
export const updateBossBattle = (gameId: number, bossId: number, data: UpdateBossBattleInput) =>
api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}`, data)
export const deleteBossBattle = (gameId: number, bossId: number) =>
api.del(`/games/${gameId}/bosses/${bossId}`)
export const setBossTeam = (gameId: number, bossId: number, team: BossPokemonInput[]) =>
api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}/pokemon`, team)