Add ESLint for TypeScript/React linting
- Install eslint, typescript-eslint, eslint-plugin-react-hooks - Configure eslint.config.js with flat config format - Add type: module to package.json - Fix unused variable issues (prefix with underscore) - Add Makefile targets: lint-frontend, fix-frontend
This commit is contained in:
parent
30583805cd
commit
4b394b0698
12 changed files with 1467 additions and 16 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -28,4 +28,5 @@ next_pr.md
|
|||
|
||||
# Notes
|
||||
notes/
|
||||
prompts/
|
||||
.coverage
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -1,4 +1,4 @@
|
|||
.PHONY: install-backend install-frontend install setup-hooks backend frontend db db-stop db-ready db-seed dev test test-backend test-frontend test-e2e typecheck generate-types generate-types-standalone check-types-fresh check-constants lint-backend format-backend fix-backend security-backend
|
||||
.PHONY: install-backend install-frontend install setup-hooks backend frontend db db-stop db-ready db-seed dev test test-backend test-frontend test-e2e typecheck generate-types generate-types-standalone check-types-fresh check-constants lint-backend format-backend fix-backend security-backend lint-frontend fix-frontend
|
||||
|
||||
-include .env
|
||||
export
|
||||
|
|
@ -105,3 +105,9 @@ fix-backend:
|
|||
|
||||
security-backend:
|
||||
cd backend && uv run bandit -r . -c pyproject.toml
|
||||
|
||||
lint-frontend:
|
||||
cd frontend && npm run lint
|
||||
|
||||
fix-frontend:
|
||||
cd frontend && npm run lint:fix
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { formatDate, formatDisplayDate, getDateRange, formatTimeString, isWeeken
|
|||
|
||||
const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays } = constants.booking;
|
||||
|
||||
type AvailabilityDay = components["schemas"]["AvailabilityDay"];
|
||||
type _AvailabilityDay = components["schemas"]["AvailabilityDay"];
|
||||
type AvailabilityResponse = components["schemas"]["AvailabilityResponse"];
|
||||
type TimeSlot = components["schemas"]["TimeSlot"];
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import constants from "../../../../shared/constants.json";
|
|||
const { READY, SPENT, REVOKED } = constants.inviteStatuses;
|
||||
|
||||
// Use generated types from OpenAPI schema
|
||||
type InviteRecord = components["schemas"]["InviteResponse"];
|
||||
type _InviteRecord = components["schemas"]["InviteResponse"];
|
||||
type PaginatedInvites = components["schemas"]["PaginatedResponse_InviteResponse_"];
|
||||
type UserOption = components["schemas"]["AdminUserResponse"];
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import { useRequireAuth } from "../hooks/useRequireAuth";
|
|||
import { components } from "../generated/api";
|
||||
|
||||
// Use generated types from OpenAPI schema
|
||||
type CounterRecord = components["schemas"]["CounterRecordResponse"];
|
||||
type SumRecord = components["schemas"]["SumRecordResponse"];
|
||||
type _CounterRecord = components["schemas"]["CounterRecordResponse"];
|
||||
type _SumRecord = components["schemas"]["SumRecordResponse"];
|
||||
type PaginatedCounterRecords = components["schemas"]["PaginatedResponse_CounterRecordResponse_"];
|
||||
type PaginatedSumRecords = components["schemas"]["PaginatedResponse_SumRecordResponse_"];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { test, expect, Page } from "@playwright/test";
|
||||
import { formatDateLocal, getTomorrowDateStr } from "./helpers/date";
|
||||
import { getTomorrowDateStr } from "./helpers/date";
|
||||
import { API_URL, REGULAR_USER, ADMIN_USER, clearAuth, loginUser } from "./helpers/auth";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { test, expect, Page } from "@playwright/test";
|
||||
import { formatDateLocal, getTomorrowDateStr } from "./helpers/date";
|
||||
import { test, expect } from "@playwright/test";
|
||||
import { getTomorrowDateStr } from "./helpers/date";
|
||||
import { API_URL, REGULAR_USER, ADMIN_USER, clearAuth, loginUser } from "./helpers/auth";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { test, expect, Page } from "@playwright/test";
|
||||
import { formatDateLocal, getTomorrowDateStr } from "./helpers/date";
|
||||
import { getTomorrowDateStr } from "./helpers/date";
|
||||
import { API_URL, REGULAR_USER, ADMIN_USER, clearAuth, loginUser } from "./helpers/auth";
|
||||
|
||||
/**
|
||||
|
|
@ -265,7 +265,7 @@ test.describe("Booking Page - With Availability", () => {
|
|||
|
||||
// Click any slot (3rd to avoid conflicts)
|
||||
const slotToBook = slotButtons.nth(2);
|
||||
const slotText = await slotToBook.textContent();
|
||||
const _slotText = await slotToBook.textContent();
|
||||
await slotToBook.click();
|
||||
|
||||
// Book it
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ test.describe("Profile - Unauthenticated Access", () => {
|
|||
await expect(page).toHaveURL("/login");
|
||||
});
|
||||
|
||||
test("profile API requires authentication", async ({ page, request }) => {
|
||||
test("profile API requires authentication", async ({ page: _page, request }) => {
|
||||
const response = await request.get(`${API_URL}/api/profile`);
|
||||
expect(response.status()).toBe(401);
|
||||
});
|
||||
|
|
|
|||
31
frontend/eslint.config.js
Normal file
31
frontend/eslint.config.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import eslint from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import reactHooks from 'eslint-plugin-react-hooks';
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
plugins: {
|
||||
'react-hooks': reactHooks,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
||||
],
|
||||
// Downgrade to warnings - existing patterns use these
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
'react-hooks/set-state-in-effect': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
'.next/**',
|
||||
'node_modules/**',
|
||||
'app/generated/**',
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
1414
frontend/package-lock.json
generated
1414
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -2,13 +2,16 @@
|
|||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"test": "vitest run",
|
||||
"test:e2e": "playwright test",
|
||||
"generate-api-types": "openapi-typescript http://localhost:8000/openapi.json -o app/generated/api.ts"
|
||||
"generate-api-types": "openapi-typescript http://localhost:8000/openapi.json -o app/generated/api.ts",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"bech32": "^2.0.0",
|
||||
|
|
@ -17,14 +20,18 @@
|
|||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@types/node": "25.0.3",
|
||||
"@types/react": "19.2.7",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"jsdom": "^26.0.0",
|
||||
"openapi-typescript": "^7.10.1",
|
||||
"typescript": "5.9.3",
|
||||
"typescript-eslint": "^8.50.0",
|
||||
"vitest": "^2.1.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue