Add pre-commit hooks for linting and formatting
Set up pre-commit framework with ruff (backend) and ESLint/Prettier/tsc (frontend) hooks to catch issues locally before CI. Auto-format all frontend files with Prettier to comply with the new check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,12 @@ import type {
|
||||
|
||||
// --- Queries ---
|
||||
|
||||
export function usePokemonList(search?: string, limit = 50, offset = 0, type?: string) {
|
||||
export function usePokemonList(
|
||||
search?: string,
|
||||
limit = 50,
|
||||
offset = 0,
|
||||
type?: string
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ['pokemon', { search, limit, offset, type }],
|
||||
queryFn: () => adminApi.listPokemon(search, limit, offset, type),
|
||||
@@ -87,8 +92,13 @@ export function useCreateRoute(gameId: number) {
|
||||
export function useUpdateRoute(gameId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ routeId, data }: { routeId: number; data: UpdateRouteInput }) =>
|
||||
adminApi.updateRoute(gameId, routeId, data),
|
||||
mutationFn: ({
|
||||
routeId,
|
||||
data,
|
||||
}: {
|
||||
routeId: number
|
||||
data: UpdateRouteInput
|
||||
}) => adminApi.updateRoute(gameId, routeId, data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
||||
@@ -114,7 +124,8 @@ export function useDeleteRoute(gameId: number) {
|
||||
export function useReorderRoutes(gameId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (routes: RouteReorderItem[]) => adminApi.reorderRoutes(gameId, routes),
|
||||
mutationFn: (routes: RouteReorderItem[]) =>
|
||||
adminApi.reorderRoutes(gameId, routes),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
||||
@@ -166,11 +177,20 @@ export function useDeletePokemon() {
|
||||
export function useBulkImportPokemon() {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (items: Array<{ pokeapiId: number; nationalDex: number; name: string; types: string[]; spriteUrl?: string | null }>) =>
|
||||
adminApi.bulkImportPokemon(items),
|
||||
mutationFn: (
|
||||
items: Array<{
|
||||
pokeapiId: number
|
||||
nationalDex: number
|
||||
name: string
|
||||
types: string[]
|
||||
spriteUrl?: string | null
|
||||
}>
|
||||
) => adminApi.bulkImportPokemon(items),
|
||||
onSuccess: (result) => {
|
||||
qc.invalidateQueries({ queryKey: ['pokemon'] })
|
||||
toast.success(`Import complete: ${result.created} created, ${result.updated} updated`)
|
||||
toast.success(
|
||||
`Import complete: ${result.created} created, ${result.updated} updated`
|
||||
)
|
||||
},
|
||||
onError: (err) => toast.error(`Import failed: ${err.message}`),
|
||||
})
|
||||
@@ -182,7 +202,9 @@ export function useBulkImportEvolutions() {
|
||||
mutationFn: (items: unknown[]) => adminApi.bulkImportEvolutions(items),
|
||||
onSuccess: (result) => {
|
||||
qc.invalidateQueries({ queryKey: ['evolutions'] })
|
||||
toast.success(`Import complete: ${result.created} created, ${result.updated} updated`)
|
||||
toast.success(
|
||||
`Import complete: ${result.created} created, ${result.updated} updated`
|
||||
)
|
||||
},
|
||||
onError: (err) => toast.error(`Import failed: ${err.message}`),
|
||||
})
|
||||
@@ -195,7 +217,9 @@ export function useBulkImportRoutes(gameId: number) {
|
||||
onSuccess: (result) => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId] })
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'routes'] })
|
||||
toast.success(`Import complete: ${result.created} routes, ${result.updated} encounters`)
|
||||
toast.success(
|
||||
`Import complete: ${result.created} routes, ${result.updated} encounters`
|
||||
)
|
||||
},
|
||||
onError: (err) => toast.error(`Import failed: ${err.message}`),
|
||||
})
|
||||
@@ -215,7 +239,12 @@ export function useBulkImportBosses(gameId: number) {
|
||||
|
||||
// --- Evolution Queries & Mutations ---
|
||||
|
||||
export function useEvolutionList(search?: string, limit = 50, offset = 0, trigger?: string) {
|
||||
export function useEvolutionList(
|
||||
search?: string,
|
||||
limit = 50,
|
||||
offset = 0,
|
||||
trigger?: string
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ['evolutions', { search, limit, offset, trigger }],
|
||||
queryFn: () => adminApi.listEvolutions(search, limit, offset, trigger),
|
||||
@@ -277,8 +306,13 @@ export function useAddRouteEncounter(routeId: number) {
|
||||
export function useUpdateRouteEncounter(routeId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ encounterId, data }: { encounterId: number; data: UpdateRouteEncounterInput }) =>
|
||||
adminApi.updateRouteEncounter(routeId, encounterId, data),
|
||||
mutationFn: ({
|
||||
encounterId,
|
||||
data,
|
||||
}: {
|
||||
encounterId: number
|
||||
data: UpdateRouteEncounterInput
|
||||
}) => adminApi.updateRouteEncounter(routeId, encounterId, data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['routes', routeId, 'pokemon'] })
|
||||
toast.success('Encounter updated')
|
||||
@@ -305,32 +339,41 @@ export function useRemoveRouteEncounter(routeId: number) {
|
||||
export function useCreateBossBattle(gameId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (data: CreateBossBattleInput) => adminApi.createBossBattle(gameId, data),
|
||||
mutationFn: (data: CreateBossBattleInput) =>
|
||||
adminApi.createBossBattle(gameId, data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'bosses'] })
|
||||
toast.success('Boss battle created')
|
||||
},
|
||||
onError: (err) => toast.error(`Failed to create boss battle: ${err.message}`),
|
||||
onError: (err) =>
|
||||
toast.error(`Failed to create boss battle: ${err.message}`),
|
||||
})
|
||||
}
|
||||
|
||||
export function useUpdateBossBattle(gameId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ bossId, data }: { bossId: number; data: UpdateBossBattleInput }) =>
|
||||
adminApi.updateBossBattle(gameId, bossId, data),
|
||||
mutationFn: ({
|
||||
bossId,
|
||||
data,
|
||||
}: {
|
||||
bossId: number
|
||||
data: UpdateBossBattleInput
|
||||
}) => adminApi.updateBossBattle(gameId, bossId, data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'bosses'] })
|
||||
toast.success('Boss battle updated')
|
||||
},
|
||||
onError: (err) => toast.error(`Failed to update boss battle: ${err.message}`),
|
||||
onError: (err) =>
|
||||
toast.error(`Failed to update boss battle: ${err.message}`),
|
||||
})
|
||||
}
|
||||
|
||||
export function useReorderBosses(gameId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (bosses: BossReorderItem[]) => adminApi.reorderBosses(gameId, bosses),
|
||||
mutationFn: (bosses: BossReorderItem[]) =>
|
||||
adminApi.reorderBosses(gameId, bosses),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'bosses'] })
|
||||
toast.success('Bosses reordered')
|
||||
@@ -347,14 +390,16 @@ export function useDeleteBossBattle(gameId: number) {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'bosses'] })
|
||||
toast.success('Boss battle deleted')
|
||||
},
|
||||
onError: (err) => toast.error(`Failed to delete boss battle: ${err.message}`),
|
||||
onError: (err) =>
|
||||
toast.error(`Failed to delete boss battle: ${err.message}`),
|
||||
})
|
||||
}
|
||||
|
||||
export function useSetBossTeam(gameId: number, bossId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (team: BossPokemonInput[]) => adminApi.setBossTeam(gameId, bossId, team),
|
||||
mutationFn: (team: BossPokemonInput[]) =>
|
||||
adminApi.setBossTeam(gameId, bossId, team),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['games', gameId, 'bosses'] })
|
||||
toast.success('Boss team updated')
|
||||
@@ -393,7 +438,8 @@ export function useDeleteGenlocke() {
|
||||
export function useAddGenlockeLeg(genlockeId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (data: AddGenlockeLegInput) => adminApi.addGenlockeLeg(genlockeId, data),
|
||||
mutationFn: (data: AddGenlockeLegInput) =>
|
||||
adminApi.addGenlockeLeg(genlockeId, data),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['genlockes'] })
|
||||
qc.invalidateQueries({ queryKey: ['genlockes', genlockeId] })
|
||||
@@ -406,7 +452,8 @@ export function useAddGenlockeLeg(genlockeId: number) {
|
||||
export function useDeleteGenlockeLeg(genlockeId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: (legId: number) => adminApi.deleteGenlockeLeg(genlockeId, legId),
|
||||
mutationFn: (legId: number) =>
|
||||
adminApi.deleteGenlockeLeg(genlockeId, legId),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['genlockes'] })
|
||||
qc.invalidateQueries({ queryKey: ['genlockes', genlockeId] })
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'sonner'
|
||||
import { getGameBosses, getBossResults, createBossResult, deleteBossResult } from '../api/bosses'
|
||||
import {
|
||||
getGameBosses,
|
||||
getBossResults,
|
||||
createBossResult,
|
||||
deleteBossResult,
|
||||
} from '../api/bosses'
|
||||
import type { CreateBossResultInput } from '../types/game'
|
||||
|
||||
export function useGameBosses(gameId: number | null, all?: boolean) {
|
||||
|
||||
@@ -22,13 +22,8 @@ export function useCreateEncounter(runId: number) {
|
||||
export function useUpdateEncounter(runId: number) {
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
data,
|
||||
}: {
|
||||
id: number
|
||||
data: UpdateEncounterInput
|
||||
}) => updateEncounter(id, data),
|
||||
mutationFn: ({ id, data }: { id: number; data: UpdateEncounterInput }) =>
|
||||
updateEncounter(id, data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['runs', runId] })
|
||||
},
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { advanceLeg, createGenlocke, getGamesByRegion, getGenlockes, getGenlocke, getGenlockeGraveyard, getGenlockeLineages, getLegSurvivors } from '../api/genlockes'
|
||||
import {
|
||||
advanceLeg,
|
||||
createGenlocke,
|
||||
getGamesByRegion,
|
||||
getGenlockes,
|
||||
getGenlocke,
|
||||
getGenlockeGraveyard,
|
||||
getGenlockeLineages,
|
||||
getLegSurvivors,
|
||||
} from '../api/genlockes'
|
||||
import type { CreateGenlockeInput } from '../types/game'
|
||||
|
||||
export function useGenlockes() {
|
||||
@@ -48,7 +57,11 @@ export function useCreateGenlocke() {
|
||||
})
|
||||
}
|
||||
|
||||
export function useLegSurvivors(genlockeId: number, legOrder: number, enabled: boolean) {
|
||||
export function useLegSurvivors(
|
||||
genlockeId: number,
|
||||
legOrder: number,
|
||||
enabled: boolean
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ['genlockes', genlockeId, 'legs', legOrder, 'survivors'],
|
||||
queryFn: () => getLegSurvivors(genlockeId, legOrder),
|
||||
@@ -59,8 +72,20 @@ export function useLegSurvivors(genlockeId: number, legOrder: number, enabled: b
|
||||
export function useAdvanceLeg() {
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ genlockeId, legOrder, transferEncounterIds }: { genlockeId: number; legOrder: number; transferEncounterIds?: number[] }) =>
|
||||
advanceLeg(genlockeId, legOrder, transferEncounterIds ? { transferEncounterIds } : undefined),
|
||||
mutationFn: ({
|
||||
genlockeId,
|
||||
legOrder,
|
||||
transferEncounterIds,
|
||||
}: {
|
||||
genlockeId: number
|
||||
legOrder: number
|
||||
transferEncounterIds?: number[]
|
||||
}) =>
|
||||
advanceLeg(
|
||||
genlockeId,
|
||||
legOrder,
|
||||
transferEncounterIds ? { transferEncounterIds } : undefined
|
||||
),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['runs'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['genlockes'] })
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { getPokemon, fetchPokemonFamilies, fetchPokemonEncounterLocations, fetchPokemonEvolutionChain } from '../api/pokemon'
|
||||
import {
|
||||
getPokemon,
|
||||
fetchPokemonFamilies,
|
||||
fetchPokemonEncounterLocations,
|
||||
fetchPokemonEvolutionChain,
|
||||
} from '../api/pokemon'
|
||||
|
||||
export function usePokemon(id: number | null) {
|
||||
return useQuery({
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'sonner'
|
||||
import { getRuns, getRun, createRun, updateRun, deleteRun, getNamingCategories, getNameSuggestions } from '../api/runs'
|
||||
import {
|
||||
getRuns,
|
||||
getRun,
|
||||
createRun,
|
||||
updateRun,
|
||||
deleteRun,
|
||||
getNamingCategories,
|
||||
getNameSuggestions,
|
||||
} from '../api/runs'
|
||||
import type { CreateRunInput, UpdateRunInput } from '../types/game'
|
||||
|
||||
export function useRuns() {
|
||||
@@ -60,7 +68,10 @@ export function useNamingCategories() {
|
||||
})
|
||||
}
|
||||
|
||||
export function useNameSuggestions(runId: number | null, pokemonId?: number | null) {
|
||||
export function useNameSuggestions(
|
||||
runId: number | null,
|
||||
pokemonId?: number | null
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ['name-suggestions', runId, pokemonId ?? null],
|
||||
queryFn: () => getNameSuggestions(runId!, 10, pokemonId ?? undefined),
|
||||
|
||||
Reference in New Issue
Block a user