- Update fetch_pokeapi.py to import all 1025 Pokemon species instead of only those appearing in encounters - Add paginated response for /pokemon endpoint with total count - Add pagination controls to AdminPokemon page (First/Prev/Next/Last) - Show current page and total count in admin UI - Add bean for Pokemon forms support task - Update UX improvements bean with route grouping polish item Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
165 lines
4.9 KiB
TypeScript
165 lines
4.9 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
import * as adminApi from '../api/admin'
|
|
import type {
|
|
CreateGameInput,
|
|
UpdateGameInput,
|
|
CreateRouteInput,
|
|
UpdateRouteInput,
|
|
RouteReorderItem,
|
|
CreatePokemonInput,
|
|
UpdatePokemonInput,
|
|
CreateRouteEncounterInput,
|
|
UpdateRouteEncounterInput,
|
|
} from '../types'
|
|
|
|
// --- Queries ---
|
|
|
|
export function usePokemonList(search?: string, limit = 50, offset = 0) {
|
|
return useQuery({
|
|
queryKey: ['pokemon', { search, limit, offset }],
|
|
queryFn: () => adminApi.listPokemon(search, limit, offset),
|
|
})
|
|
}
|
|
|
|
// --- Game Mutations ---
|
|
|
|
export function useCreateGame() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (data: CreateGameInput) => adminApi.createGame(data),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['games'] }),
|
|
})
|
|
}
|
|
|
|
export function useUpdateGame() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: number; data: UpdateGameInput }) =>
|
|
adminApi.updateGame(id, data),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['games'] }),
|
|
})
|
|
}
|
|
|
|
export function useDeleteGame() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (id: number) => adminApi.deleteGame(id),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['games'] }),
|
|
})
|
|
}
|
|
|
|
// --- Route Mutations ---
|
|
|
|
export function useCreateRoute(gameId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (data: CreateRouteInput) => adminApi.createRoute(gameId, data),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
|
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useUpdateRoute(gameId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ routeId, data }: { routeId: number; data: UpdateRouteInput }) =>
|
|
adminApi.updateRoute(gameId, routeId, data),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
|
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useDeleteRoute(gameId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (routeId: number) => adminApi.deleteRoute(gameId, routeId),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
|
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useReorderRoutes(gameId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (routes: RouteReorderItem[]) => adminApi.reorderRoutes(gameId, routes),
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
|
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
|
},
|
|
})
|
|
}
|
|
|
|
// --- Pokemon Mutations ---
|
|
|
|
export function useCreatePokemon() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (data: CreatePokemonInput) => adminApi.createPokemon(data),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['pokemon'] }),
|
|
})
|
|
}
|
|
|
|
export function useUpdatePokemon() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: number; data: UpdatePokemonInput }) =>
|
|
adminApi.updatePokemon(id, data),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['pokemon'] }),
|
|
})
|
|
}
|
|
|
|
export function useDeletePokemon() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (id: number) => adminApi.deletePokemon(id),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['pokemon'] }),
|
|
})
|
|
}
|
|
|
|
export function useBulkImportPokemon() {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (items: Array<{ nationalDex: number; name: string; types: string[]; spriteUrl?: string | null }>) =>
|
|
adminApi.bulkImportPokemon(items),
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ['pokemon'] }),
|
|
})
|
|
}
|
|
|
|
// --- Route Encounter Mutations ---
|
|
|
|
export function useAddRouteEncounter(routeId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (data: CreateRouteEncounterInput) =>
|
|
adminApi.addRouteEncounter(routeId, data),
|
|
onSuccess: () =>
|
|
qc.invalidateQueries({ queryKey: ['routes', routeId, 'pokemon'] }),
|
|
})
|
|
}
|
|
|
|
export function useUpdateRouteEncounter(routeId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: ({ encounterId, data }: { encounterId: number; data: UpdateRouteEncounterInput }) =>
|
|
adminApi.updateRouteEncounter(routeId, encounterId, data),
|
|
onSuccess: () =>
|
|
qc.invalidateQueries({ queryKey: ['routes', routeId, 'pokemon'] }),
|
|
})
|
|
}
|
|
|
|
export function useRemoveRouteEncounter(routeId: number) {
|
|
const qc = useQueryClient()
|
|
return useMutation({
|
|
mutationFn: (encounterId: number) =>
|
|
adminApi.removeRouteEncounter(routeId, encounterId),
|
|
onSuccess: () =>
|
|
qc.invalidateQueries({ queryKey: ['routes', routeId, 'pokemon'] }),
|
|
})
|
|
}
|