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:
@@ -3,12 +3,21 @@ import { useParams, Link } from 'react-router-dom'
|
||||
import { useRun, useUpdateRun, useNamingCategories } from '../hooks/useRuns'
|
||||
import { useGameRoutes } from '../hooks/useGames'
|
||||
import { useCreateEncounter, useUpdateEncounter } from '../hooks/useEncounters'
|
||||
import { StatCard, PokemonCard, RuleBadges, StatusChangeModal, EndRunModal } from '../components'
|
||||
import {
|
||||
StatCard,
|
||||
PokemonCard,
|
||||
RuleBadges,
|
||||
StatusChangeModal,
|
||||
EndRunModal,
|
||||
} from '../components'
|
||||
import type { RunStatus, EncounterDetail } from '../types'
|
||||
|
||||
type TeamSortKey = 'route' | 'level' | 'species' | 'dex'
|
||||
|
||||
function sortEncounters(encounters: EncounterDetail[], key: TeamSortKey): EncounterDetail[] {
|
||||
function sortEncounters(
|
||||
encounters: EncounterDetail[],
|
||||
key: TeamSortKey
|
||||
): EncounterDetail[] {
|
||||
return [...encounters].sort((a, b) => {
|
||||
switch (key) {
|
||||
case 'route':
|
||||
@@ -21,7 +30,10 @@ function sortEncounters(encounters: EncounterDetail[], key: TeamSortKey): Encoun
|
||||
return nameA.localeCompare(nameB)
|
||||
}
|
||||
case 'dex':
|
||||
return (a.currentPokemon ?? a.pokemon).nationalDex - (b.currentPokemon ?? b.pokemon).nationalDex
|
||||
return (
|
||||
(a.currentPokemon ?? a.pokemon).nationalDex -
|
||||
(b.currentPokemon ?? b.pokemon).nationalDex
|
||||
)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
@@ -29,9 +41,9 @@ function sortEncounters(encounters: EncounterDetail[], key: TeamSortKey): Encoun
|
||||
}
|
||||
|
||||
const statusStyles: Record<RunStatus, string> = {
|
||||
active: 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300',
|
||||
completed:
|
||||
'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300',
|
||||
active:
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300',
|
||||
completed: 'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300',
|
||||
failed: 'bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300',
|
||||
}
|
||||
|
||||
@@ -59,12 +71,24 @@ export function RunDashboard() {
|
||||
|
||||
const encounters = run?.encounters ?? []
|
||||
const alive = useMemo(
|
||||
() => sortEncounters(encounters.filter((e) => e.status === 'caught' && e.faintLevel === null), teamSort),
|
||||
[encounters, teamSort],
|
||||
() =>
|
||||
sortEncounters(
|
||||
encounters.filter(
|
||||
(e) => e.status === 'caught' && e.faintLevel === null
|
||||
),
|
||||
teamSort
|
||||
),
|
||||
[encounters, teamSort]
|
||||
)
|
||||
const dead = useMemo(
|
||||
() => sortEncounters(encounters.filter((e) => e.status === 'caught' && e.faintLevel !== null), teamSort),
|
||||
[encounters, teamSort],
|
||||
() =>
|
||||
sortEncounters(
|
||||
encounters.filter(
|
||||
(e) => e.status === 'caught' && e.faintLevel !== null
|
||||
),
|
||||
teamSort
|
||||
),
|
||||
[encounters, teamSort]
|
||||
)
|
||||
|
||||
if (isLoading) {
|
||||
@@ -111,7 +135,10 @@ export function RunDashboard() {
|
||||
{run.name}
|
||||
</h1>
|
||||
<p className="text-gray-600 dark:text-gray-400 mt-1">
|
||||
{run.game.name} · {run.game.region.charAt(0).toUpperCase() + run.game.region.slice(1)} · Started{' '}
|
||||
{run.game.name} ·{' '}
|
||||
{run.game.region.charAt(0).toUpperCase() +
|
||||
run.game.region.slice(1)}{' '}
|
||||
· Started{' '}
|
||||
{new Date(run.startedAt).toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
@@ -137,7 +164,9 @@ export function RunDashboard() {
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-2xl">{run.status === 'completed' ? '\u{1f3c6}' : '\u{1faa6}'}</span>
|
||||
<span className="text-2xl">
|
||||
{run.status === 'completed' ? '\u{1f3c6}' : '\u{1faa6}'}
|
||||
</span>
|
||||
<div>
|
||||
<p
|
||||
className={`font-semibold ${
|
||||
@@ -222,7 +251,8 @@ export function RunDashboard() {
|
||||
) : (
|
||||
<span className="text-sm text-gray-900 dark:text-gray-100">
|
||||
{run.namingScheme
|
||||
? run.namingScheme.charAt(0).toUpperCase() + run.namingScheme.slice(1)
|
||||
? run.namingScheme.charAt(0).toUpperCase() +
|
||||
run.namingScheme.slice(1)
|
||||
: 'None'}
|
||||
</span>
|
||||
)}
|
||||
@@ -329,7 +359,7 @@ export function RunDashboard() {
|
||||
onConfirm={(status) => {
|
||||
updateRun.mutate(
|
||||
{ status },
|
||||
{ onSuccess: () => setShowEndRun(false) },
|
||||
{ onSuccess: () => setShowEndRun(false) }
|
||||
)
|
||||
}}
|
||||
onClose={() => setShowEndRun(false)}
|
||||
|
||||
Reference in New Issue
Block a user