Align repo config with global development standards
Some checks failed
CI / backend-lint (push) Failing after 1m4s
CI / actions-lint (push) Failing after 6s
CI / frontend-lint (push) Successful in 59s

- Add missing tsconfig strictness flags (noUncheckedIndexedAccess,
  exactOptionalPropertyTypes, noImplicitOverride,
  noPropertyAccessFromIndexSignature) and fix all resulting type errors
- Replace ESLint/Prettier with oxlint 1.48.0 and oxfmt 0.33.0
- Pin all frontend and backend dependencies to exact versions
- Pin GitHub Actions to SHA hashes with persist-credentials: false
- Fix CI Python version mismatch (3.12 -> 3.14) and ruff target-version
- Add vitest 4.0.18 with jsdom environment for frontend testing
- Add ty 0.0.17 for Python type checking (non-blocking in CI)
- Add actionlint and zizmor CI job for workflow linting and security audit
- Add Dependabot config for npm, pip, and github-actions
- Update CLAUDE.md and pre-commit hooks to reflect new tooling
- Ignore Claude Code sandbox artifacts in gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 20:39:41 +01:00
parent e4814250db
commit 3a64661760
91 changed files with 2073 additions and 3215 deletions

View File

@@ -18,7 +18,7 @@ interface GameGridProps {
games: Game[]
selectedId: number | null
onSelect: (game: Game) => void
runs?: NuzlockeRun[]
runs?: NuzlockeRun[] | undefined
}
export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) {
@@ -27,38 +27,26 @@ export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) {
const [hideWithActiveRun, setHideWithActiveRun] = useState(false)
const [hideCompleted, setHideCompleted] = useState(false)
const generations = useMemo(
() => [...new Set(games.map((g) => g.generation))].sort(),
[games]
)
const generations = useMemo(() => [...new Set(games.map((g) => g.generation))].sort(), [games])
const regions = useMemo(
() => [...new Set(games.map((g) => g.region))].sort(),
[games]
)
const regions = useMemo(() => [...new Set(games.map((g) => g.region))].sort(), [games])
const activeRunGameIds = useMemo(() => {
if (!runs) return new Set<number>()
return new Set(
runs.filter((r) => r.status === 'active').map((r) => r.gameId)
)
return new Set(runs.filter((r) => r.status === 'active').map((r) => r.gameId))
}, [runs])
const completedRunGameIds = useMemo(() => {
if (!runs) return new Set<number>()
return new Set(
runs.filter((r) => r.status === 'completed').map((r) => r.gameId)
)
return new Set(runs.filter((r) => r.status === 'completed').map((r) => r.gameId))
}, [runs])
const filtered = useMemo(() => {
let result = games
if (filter) result = result.filter((g) => g.generation === filter)
if (regionFilter) result = result.filter((g) => g.region === regionFilter)
if (hideWithActiveRun)
result = result.filter((g) => !activeRunGameIds.has(g.id))
if (hideCompleted)
result = result.filter((g) => !completedRunGameIds.has(g.id))
if (hideWithActiveRun) result = result.filter((g) => !activeRunGameIds.has(g.id))
if (hideCompleted) result = result.filter((g) => !completedRunGameIds.has(g.id))
return result
}, [
games,
@@ -91,9 +79,7 @@ export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) {
<div className="space-y-6">
<div className="space-y-3">
<div className="flex flex-wrap items-center gap-2">
<span className="text-xs font-medium text-gray-500 dark:text-gray-400 mr-1">
Gen:
</span>
<span className="text-xs font-medium text-gray-500 dark:text-gray-400 mr-1">Gen:</span>
<button
type="button"
onClick={() => setFilter(null)}
@@ -114,9 +100,7 @@ export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) {
</div>
<div className="flex flex-wrap items-center gap-2">
<span className="text-xs font-medium text-gray-500 dark:text-gray-400 mr-1">
Region:
</span>
<span className="text-xs font-medium text-gray-500 dark:text-gray-400 mr-1">Region:</span>
<button
type="button"
onClick={() => setRegionFilter(null)}