diff --git a/.oxlintrc.json b/.oxlintrc.json index aae4b03..4417162 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -37,9 +37,14 @@ "react/self-closing-comp": "warn", "import/no-duplicates": "error", + "import/no-unassigned-import": ["error", { + "allow": ["**/*.css", "@testing-library/jest-dom", "@testing-library/cypress/add-commands"] + }], "no-shadow": "error", - "unicorn/consistent-function-scoping": "error" + "unicorn/consistent-function-scoping": "error", + "unicorn/prefer-add-event-listener": "error", + "unicorn/require-module-specifiers": "error" }, "overrides": [ { diff --git a/app/hooks/useDraftNotifications.ts b/app/hooks/useDraftNotifications.ts index 7952c81..036eea0 100644 --- a/app/hooks/useDraftNotifications.ts +++ b/app/hooks/useDraftNotifications.ts @@ -44,18 +44,20 @@ export function useDraftNotifications(seasonId: string, userId: string) { // would still be null at that point without the flag). let aborted = false; let permissionStatus: PermissionStatus | null = null; + let changeHandler: (() => void) | null = null; navigator.permissions .query({ name: "notifications" }) .then((status) => { if (aborted) return; permissionStatus = status; - status.onchange = () => { + changeHandler = () => { setPermissionState(status.state as NotificationPermission); // If permission was revoked, disable notifications if (status.state !== "granted") { setEnabledState(false); } }; + status.addEventListener("change", changeHandler); }) .catch(() => { // Permissions API not available in all environments; silently ignore @@ -63,8 +65,8 @@ export function useDraftNotifications(seasonId: string, userId: string) { return () => { aborted = true; - if (permissionStatus) { - permissionStatus.onchange = null; + if (permissionStatus && changeHandler) { + permissionStatus.removeEventListener("change", changeHandler); } }; }, [seasonId, userId]); @@ -120,7 +122,7 @@ export function useDraftNotifications(seasonId: string, userId: string) { body, tag: `draft-${seasonId}`, }); - n.onclick = () => window.focus(); + n.addEventListener("click", () => window.focus()); }, [enabled, seasonId] ); diff --git a/app/routes/admin.data-sync.tsx b/app/routes/admin.data-sync.tsx index 5cd41b7..69557e8 100644 --- a/app/routes/admin.data-sync.tsx +++ b/app/routes/admin.data-sync.tsx @@ -139,14 +139,14 @@ export default function DataSync({ loaderData }: Route.ComponentProps) { } const reader = new FileReader(); - reader.onload = (event) => { + reader.addEventListener("load", (event) => { const fileData = event.target?.result as string; const formData = new FormData(); formData.append("intent", "import"); formData.append("mode", importMode); formData.append("fileData", fileData); fetcher.submit(formData, { method: "POST" }); - }; + }); reader.readAsText(selectedFile); }; diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index e8d4e2d..beb10f7 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -19,4 +19,3 @@ declare global { } } -export {};