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:
@@ -42,24 +42,29 @@ export function AdminRouteDetail() {
|
||||
|
||||
const sortedRoutes = useMemo(
|
||||
() => [...(game?.routes ?? [])].sort((a, b) => a.order - b.order),
|
||||
[game?.routes],
|
||||
[game?.routes]
|
||||
)
|
||||
const currentIndex = sortedRoutes.findIndex((r) => r.id === rId)
|
||||
const route = currentIndex >= 0 ? sortedRoutes[currentIndex] : undefined
|
||||
const prevRoute = currentIndex > 0 ? sortedRoutes[currentIndex - 1] : undefined
|
||||
const prevRoute =
|
||||
currentIndex > 0 ? sortedRoutes[currentIndex - 1] : undefined
|
||||
const nextRoute =
|
||||
currentIndex >= 0 && currentIndex < sortedRoutes.length - 1
|
||||
? sortedRoutes[currentIndex + 1]
|
||||
: undefined
|
||||
|
||||
const childRoutes = useMemo(
|
||||
() => (game?.routes ?? []).filter((r) => r.parentRouteId === rId).sort((a, b) => a.order - b.order),
|
||||
[game?.routes, rId],
|
||||
() =>
|
||||
(game?.routes ?? [])
|
||||
.filter((r) => r.parentRouteId === rId)
|
||||
.sort((a, b) => a.order - b.order),
|
||||
[game?.routes, rId]
|
||||
)
|
||||
|
||||
const nextChildOrder = childRoutes.length > 0
|
||||
? Math.max(...childRoutes.map((r) => r.order)) + 1
|
||||
: (route?.order ?? 0) * 10 + 1
|
||||
const nextChildOrder =
|
||||
childRoutes.length > 0
|
||||
? Math.max(...childRoutes.map((r) => r.order)) + 1
|
||||
: (route?.order ?? 0) * 10 + 1
|
||||
|
||||
const columns: Column<RouteEncounterDetail>[] = [
|
||||
{
|
||||
@@ -67,7 +72,11 @@ export function AdminRouteDetail() {
|
||||
accessor: (e) => (
|
||||
<div className="flex items-center gap-2">
|
||||
{e.pokemon.spriteUrl ? (
|
||||
<img src={e.pokemon.spriteUrl} alt={e.pokemon.name} className="w-6 h-6" />
|
||||
<img
|
||||
src={e.pokemon.spriteUrl}
|
||||
alt={e.pokemon.name}
|
||||
className="w-6 h-6"
|
||||
/>
|
||||
) : null}
|
||||
<span>
|
||||
#{e.pokemon.nationalDex} {e.pokemon.name}
|
||||
@@ -80,7 +89,9 @@ export function AdminRouteDetail() {
|
||||
{
|
||||
header: 'Levels',
|
||||
accessor: (e) =>
|
||||
e.minLevel === e.maxLevel ? `Lv ${e.minLevel}` : `Lv ${e.minLevel}-${e.maxLevel}`,
|
||||
e.minLevel === e.maxLevel
|
||||
? `Lv ${e.minLevel}`
|
||||
: `Lv ${e.minLevel}-${e.maxLevel}`,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -98,7 +109,9 @@ export function AdminRouteDetail() {
|
||||
<select
|
||||
className="text-gray-900 dark:text-gray-100 bg-transparent font-medium cursor-pointer hover:underline border-none p-0 text-sm"
|
||||
value={rId}
|
||||
onChange={(e) => navigate(`/admin/games/${gId}/routes/${e.target.value}`)}
|
||||
onChange={(e) =>
|
||||
navigate(`/admin/games/${gId}/routes/${e.target.value}`)
|
||||
}
|
||||
>
|
||||
{sortedRoutes.map((r) => (
|
||||
<option key={r.id} value={r.id}>
|
||||
@@ -162,9 +175,12 @@ export function AdminRouteDetail() {
|
||||
{showCreate && (
|
||||
<RouteEncounterFormModal
|
||||
onSubmit={(data) =>
|
||||
addEncounter.mutate({ ...data, gameId: gId } as CreateRouteEncounterInput, {
|
||||
onSuccess: () => setShowCreate(false),
|
||||
})
|
||||
addEncounter.mutate(
|
||||
{ ...data, gameId: gId } as CreateRouteEncounterInput,
|
||||
{
|
||||
onSuccess: () => setShowCreate(false),
|
||||
}
|
||||
)
|
||||
}
|
||||
onClose={() => setShowCreate(false)}
|
||||
isSubmitting={addEncounter.isPending}
|
||||
@@ -176,8 +192,11 @@ export function AdminRouteDetail() {
|
||||
encounter={editing}
|
||||
onSubmit={(data) =>
|
||||
updateEncounter.mutate(
|
||||
{ encounterId: editing.id, data: data as UpdateRouteEncounterInput },
|
||||
{ onSuccess: () => setEditing(null) },
|
||||
{
|
||||
encounterId: editing.id,
|
||||
data: data as UpdateRouteEncounterInput,
|
||||
},
|
||||
{ onSuccess: () => setEditing(null) }
|
||||
)
|
||||
}
|
||||
onClose={() => setEditing(null)}
|
||||
@@ -194,7 +213,9 @@ export function AdminRouteDetail() {
|
||||
{/* Sub-areas */}
|
||||
<div className="mt-8">
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<h3 className="text-lg font-semibold">Sub-areas ({childRoutes.length})</h3>
|
||||
<h3 className="text-lg font-semibold">
|
||||
Sub-areas ({childRoutes.length})
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => setShowCreateChild(true)}
|
||||
className="px-3 py-1.5 text-sm font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700"
|
||||
@@ -203,11 +224,16 @@ export function AdminRouteDetail() {
|
||||
</button>
|
||||
</div>
|
||||
{childRoutes.length === 0 ? (
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">No sub-areas for this route.</p>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||
No sub-areas for this route.
|
||||
</p>
|
||||
) : (
|
||||
<div className="border rounded-md dark:border-gray-700 divide-y dark:divide-gray-700">
|
||||
{childRoutes.map((child) => (
|
||||
<div key={child.id} className="flex items-center justify-between px-4 py-2">
|
||||
<div
|
||||
key={child.id}
|
||||
className="flex items-center justify-between px-4 py-2"
|
||||
>
|
||||
<Link
|
||||
to={`/admin/games/${gId}/routes/${child.id}`}
|
||||
className="text-blue-600 dark:text-blue-400 hover:underline"
|
||||
@@ -232,7 +258,7 @@ export function AdminRouteDetail() {
|
||||
onSubmit={(data) =>
|
||||
createRoute.mutate(
|
||||
{ ...data, parentRouteId: rId } as CreateRouteInput,
|
||||
{ onSuccess: () => setShowCreateChild(false) },
|
||||
{ onSuccess: () => setShowCreateChild(false) }
|
||||
)
|
||||
}
|
||||
onClose={() => setShowCreateChild(false)}
|
||||
|
||||
Reference in New Issue
Block a user