From 7282020444dc94fda95f07117ba82633dd662416 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 22 Jun 2026 00:17:18 -0400 Subject: [PATCH] chore: configure eslint rules and fix lint warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add eslint rules section downgrading strict react-hooks v7 rules to warn - Remove unnecessary Boolean() wrappers across multiple pages - Fix let→const for non-reassigned variable in AdminProgressPages - Clean up stale eslint-disable-next-line comment and trailing whitespace - Simplify setTimeout declaration in ManualPayPage --- eslint.config.js | 12 ++++++++++++ src/pages/AdminProgressPages.tsx | 2 +- src/pages/AdministratorToolPages.tsx | 11 +++++------ src/pages/grading/GradingDecisionsPage.tsx | 2 +- src/pages/payment/ManualPayPage.tsx | 3 +-- src/pages/teacher/TeacherRestPages.tsx | 2 +- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 5e6b472..ce19adc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -19,5 +19,17 @@ export default defineConfig([ ecmaVersion: 2020, globals: globals.browser, }, + rules: { + // ── New strict rules from react-hooks v7 — downgrade to warn ── + 'react-hooks/set-state-in-effect': 'warn', + 'react-hooks/exhaustive-deps': 'warn', + 'react-hooks/preserve-manual-memoization': 'warn', + 'react-hooks/immutability': 'warn', + 'react-refresh/only-export-components': 'warn', + + // ── Keep these as errors (real bugs / anti-patterns) ── + 'react-hooks/static-components': 'error', + '@typescript-eslint/no-unused-expressions': 'error', + }, }, ]) diff --git a/src/pages/AdminProgressPages.tsx b/src/pages/AdminProgressPages.tsx index 8537b2b..babf2b6 100644 --- a/src/pages/AdminProgressPages.tsx +++ b/src/pages/AdminProgressPages.tsx @@ -82,7 +82,7 @@ export function AdminEmergencyContactIndexPage() { const displayed = useMemo(() => { const q = search.trim().toLowerCase() - let rows = q + const rows = q ? flatRows.filter((r) => r.parentName.toLowerCase().includes(q) || r.students.toLowerCase().includes(q) || diff --git a/src/pages/AdministratorToolPages.tsx b/src/pages/AdministratorToolPages.tsx index babcf5a..174c8f9 100644 --- a/src/pages/AdministratorToolPages.tsx +++ b/src/pages/AdministratorToolPages.tsx @@ -2543,7 +2543,7 @@ export function AdminExamDraftsPage() { const allowedExtensions = data?.allowed_extensions ?? ['doc', 'docx', 'pdf'] const maxUploadMb = Math.max(1, Math.round((data?.max_upload_bytes ?? 12 * 1024 * 1024) / 1024 / 1024)) const classSections = data?.class_sections ?? [] - const drafts = (data?.drafts ?? []).filter((draft) => !Boolean(draft.is_legacy)) + const drafts = (data?.drafts ?? []).filter((draft) => !draft.is_legacy) const legacyByClass = data?.legacy_by_class ?? {} const draftsByClass = useMemo(() => { @@ -3933,7 +3933,6 @@ export function AdminSectionsAutoDistributePage() { async function runAll() { for (const row of rows) { - // eslint-disable-next-line no-await-in-loop await runDistribution(row) } } @@ -4318,8 +4317,8 @@ export function AdminStudentProfilesPage() { student.registration_grade, student.dob, student.registration_date, - Boolean(student.is_active) ? 'yes active' : 'no inactive', - Boolean(student.photo_consent) ? 'yes consent' : 'no consent', + student.is_active ? 'yes active' : 'no inactive', + student.photo_consent ? 'yes consent' : 'no consent', ] .map((value) => String(value ?? '').toLowerCase()) .join(' ') @@ -4391,8 +4390,8 @@ export function AdminStudentProfilesPage() { {student.age ?? '—'} {student.gender ?? '—'} {student.registration_grade ?? '—'} - {Boolean(student.is_active) ? 'Yes' : 'No'} - {Boolean(student.photo_consent) ? 'Yes' : 'No'} + {student.is_active ? 'Yes' : 'No'} + {student.photo_consent ? 'Yes' : 'No'} {formatDate(student.registration_date)} diff --git a/src/pages/grading/GradingDecisionsPage.tsx b/src/pages/grading/GradingDecisionsPage.tsx index 2e10551..d2b6a9e 100644 --- a/src/pages/grading/GradingDecisionsPage.tsx +++ b/src/pages/grading/GradingDecisionsPage.tsx @@ -182,7 +182,7 @@ export function GradingDecisionsPage() { totals.Other += 1 } - if (Boolean(row.is_trophy)) { + if (row.is_trophy) { totals.Trophy += 1 gender.trophy[bucket] += 1 } diff --git a/src/pages/payment/ManualPayPage.tsx b/src/pages/payment/ManualPayPage.tsx index 0c35887..5edae89 100644 --- a/src/pages/payment/ManualPayPage.tsx +++ b/src/pages/payment/ManualPayPage.tsx @@ -76,12 +76,11 @@ export function ManualPayPage() { }, [termFromUrl, load]) useEffect(() => { - let t: ReturnType if (searchInput.trim().length < 2) { setSuggestions([]) return } - t = setTimeout(() => { + const t = setTimeout(() => { fetchManualPaySuggest(searchInput.trim()) .then((rows) => { setSuggestions( diff --git a/src/pages/teacher/TeacherRestPages.tsx b/src/pages/teacher/TeacherRestPages.tsx index 5f1a19a..3b5c104 100644 --- a/src/pages/teacher/TeacherRestPages.tsx +++ b/src/pages/teacher/TeacherRestPages.tsx @@ -743,7 +743,7 @@ export function TeacherCalendarPage() { (row) => Boolean(row.extendedProps?.notify_teacher) && Boolean(row.extendedProps?.notify_admin) && - !Boolean(row.extendedProps?.notify_parent), + !row.extendedProps?.notify_parent, ).length return (