Add admin panel with CRUD endpoints and management UI
Add admin API endpoints for games, routes, pokemon, and route encounters with full CRUD operations including bulk import. Build admin frontend with game/route/pokemon management pages, navigation, and data tables. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
71
frontend/src/api/admin.ts
Normal file
71
frontend/src/api/admin.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { api } from './client'
|
||||
import type {
|
||||
Game,
|
||||
Route,
|
||||
Pokemon,
|
||||
RouteEncounterDetail,
|
||||
CreateGameInput,
|
||||
UpdateGameInput,
|
||||
CreateRouteInput,
|
||||
UpdateRouteInput,
|
||||
RouteReorderItem,
|
||||
CreatePokemonInput,
|
||||
UpdatePokemonInput,
|
||||
BulkImportResult,
|
||||
CreateRouteEncounterInput,
|
||||
UpdateRouteEncounterInput,
|
||||
} 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<Pokemon[]>(`/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<{ nationalDex: number; name: string; types: string[]; spriteUrl?: string | null }>) =>
|
||||
api.post<BulkImportResult>('/pokemon/bulk-import', items)
|
||||
|
||||
// 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}`)
|
||||
@@ -46,6 +46,12 @@ export const api = {
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
|
||||
put: <T>(path: string, body: unknown) =>
|
||||
request<T>(path, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
|
||||
del: <T = void>(path: string) =>
|
||||
request<T>(path, { method: 'DELETE' }),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user