diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index c5d43a6..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["next", "prettier"] -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..019f472 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,149 @@ +import { defineConfig } from "eslint/config"; +import eslintPlugin from "@eslint/js"; +import tseslintPlugin from "@typescript-eslint/eslint-plugin"; +import tseslintParser from "@typescript-eslint/parser"; +import reactPlugin from "eslint-plugin-react"; +import reactHooksPlugin from "eslint-plugin-react-hooks"; +import jsxA11yPlugin from "eslint-plugin-jsx-a11y"; +import nextPlugin from "@next/eslint-plugin-next"; + +// Global ignores configuration +// Must be in its own config object to act as global ignores +const ignoresConfig = defineConfig([ + { + name: "project/ignores", + ignores: [ + ".next/", + "node_modules/", + "public/", + ".vscode/", + "next-env.d.ts", + ], + }, +]); + +// ESLint recommended rules for JavaScript/TypeScript +const eslintConfig = defineConfig([ + { + name: "project/javascript-recommended", + files: ["**/*.{js,mjs,ts,tsx}"], + ...eslintPlugin.configs.recommended, + }, +]); + +// TypeScript configuration with type-checked rules +const typescriptConfig = defineConfig([ + { + name: "project/typescript-strict", + files: ["**/*.{ts,tsx,mjs}"], + plugins: { + "@typescript-eslint": tseslintPlugin, + }, + languageOptions: { + parser: tseslintParser, + parserOptions: { + project: ["./tsconfig.json"], + tsconfigRootDir: import.meta.dirname, + ecmaFeatures: { + jsx: true, + }, + warnOnUnsupportedTypeScriptVersion: true, + }, + }, + extends: [ + "@typescript-eslint/strict-type-checked", + "@typescript-eslint/stylistic-type-checked", + ], + rules: { + // Disable rules that conflict with TypeScript's own error checking + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/triple-slash-reference": "off", + // disabled next rule due to bug: + // https://github.com/typescript-eslint/typescript-eslint/issues/11732 + // https://github.com/eslint/eslint/issues/20272 + "@typescript-eslint/unified-signatures": "off", + // Allow ts-expect-error and ts-ignore with descriptions + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": false, + "ts-check": false, + minimumDescriptionLength: 3, + }, + ], + }, + }, + // For plain JS files, you may want to disable type-checked rules + { + name: "project/javascript-disable-type-check", + files: ["**/*.{js,mjs,cjs}"], + plugins: { + "@typescript-eslint": tseslintPlugin, + }, + extends: ["@typescript-eslint/disable-type-checked"], + }, +]); + +// React and Next.js configuration +const reactConfig = defineConfig([ + { + name: "project/react-next", + files: ["**/*.{jsx,tsx}"], + plugins: { + react: reactPlugin, + "react-hooks": reactHooksPlugin, + "jsx-a11y": jsxA11yPlugin, + "@next/next": nextPlugin, + }, + rules: { + // React recommended rules + ...reactPlugin.configs.recommended.rules, + ...reactPlugin.configs["jsx-runtime"].rules, + // React Hooks rules (use recommended-latest for latest features) + ...reactHooksPlugin.configs["recommended-latest"].rules, + // Accessibility rules (strict mode for better a11y) + ...jsxA11yPlugin.configs.strict.rules, + // Next.js recommended rules + ...nextPlugin.configs.recommended.rules, + // Next.js Core Web Vitals rules + ...nextPlugin.configs["core-web-vitals"].rules, + + // Customizations for modern React/Next.js + "react/react-in-jsx-scope": "off", // Not needed in Next.js + "react/prop-types": "off", // Use TypeScript instead + "react/no-unknown-property": "off", // Conflicts with custom attributes + "react/jsx-no-target-blank": "off", // Next.js handles this + + // Fine-tuned accessibility rules + "jsx-a11y/alt-text": [ + "warn", + { + elements: ["img"], + img: ["Image"], // Next.js Image component + }, + ], + "jsx-a11y/media-has-caption": "warn", + "jsx-a11y/aria-props": "warn", + "jsx-a11y/aria-proptypes": "warn", + "jsx-a11y/aria-unsupported-elements": "warn", + "jsx-a11y/role-has-required-aria-props": "warn", + "jsx-a11y/role-supports-aria-props": "warn", + }, + settings: { + react: { + version: "detect", // Automatically detect React version + }, + }, + }, +]); + +// Export the complete configuration +// Order matters: ignores first, then general configs, then specific overrides +export default defineConfig([ + ...ignoresConfig, + ...eslintConfig, + ...typescriptConfig, + ...reactConfig, +]); diff --git a/next.config.ts b/next.config.ts index a7672c7..8efa67c 100644 --- a/next.config.ts +++ b/next.config.ts @@ -21,7 +21,7 @@ const nextConfig: NextConfig = { "sharp", ], }, - async headers() { + headers() { return [ { source: "/(.*)", diff --git a/package.json b/package.json index 47988ee..f09f622 100644 --- a/package.json +++ b/package.json @@ -4,28 +4,28 @@ "scripts": { "dev": "pnpm open-browser && next dev --turbopack", "open-browser": "start http://localhost:3000", - "build": "next build", + "build": "pnpm run lint && next build", "start": "next start", - "lint": "next lint", - "test": "prettier . --write && next lint && next build && playwright test", - "test-only": "next lint && playwright test", + "lint": "eslint", + "lint:fix": "eslint --fix", + "test": "prettier . --write && pnpm run lint && next build && playwright test", + "test-only": "pnpm run lint && playwright test", "pretty": "prettier . --write", "pretty-check": "prettier . --check", - "pretty-lint": "prettier . --write && next lint", + "pretty-lint": "prettier . --write && pnpm run lint", "prepare": "husky" }, "dependencies": { - "@mantine/core": "^7.17.8", - "@mantine/form": "^7.17.8", - "@mantine/hooks": "^7.17.8", + "@mantine/core": "^8.3.14", + "@mantine/form": "^8.3.14", + "@mantine/hooks": "^8.3.14", "@tabler/icons-react": "^3.36.1", "@vercel/analytics": "^1.6.1", "@vercel/postgres": "^0.10.0", "@vercel/speed-insights": "^1.3.1", "bcrypt": "^6.0.0", "dotenv": "^17.2.3", - "eslint": "^9.39.2", - "next": "^15.5.10", + "next": "^16.1.6", "next-auth": "5.0.0-beta.30", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -35,20 +35,30 @@ "zod": "^4.3.6" }, "devDependencies": { - "@playwright/test": "^1.58.0", + "@eslint/js": "^9.39.2", + "@next/eslint-plugin-next": "16.1.6", + "@playwright/test": "^1.58.1", "@types/bcrypt": "^6.0.0", - "@types/node": "^24.10.9", - "@types/react": "^19.2.9", + "@types/node": "^25.2.0", + "@types/react": "^19.2.10", "@types/react-dom": "^19.2.3", - "eslint-config-next": "15.5.4", + "@typescript-eslint/eslint-plugin": "^8.54.0", + "@typescript-eslint/parser": "^8.54.0", + "eslint": "^9.39.2", + "eslint-config-next": "16.1.6", "eslint-config-prettier": "^10.1.8", + "eslint-plugin-jsx-a11y": "6.10.2", + "eslint-plugin-next": "^0.0.0", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.0.1", "husky": "^9.1.7", - "lint-staged": "^15.5.2", + "lint-staged": "^16.2.7", "postcss": "^8.5.6", "postcss-preset-mantine": "^1.18.0", "postcss-simple-vars": "^7.0.1", - "prettier": "3.6.2", - "typescript": "^5.9.3" + "prettier": "3.8.1", + "typescript": "^5.9.3", + "typescript-eslint": "8.54.0" }, "lint-staged": { "**/*": "prettier --write --ignore-unknown" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f9c505..282d6bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,41 +8,38 @@ importers: .: dependencies: "@mantine/core": - specifier: ^7.17.8 - version: 7.17.8(@mantine/hooks@7.17.8(react@19.2.4))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^8.3.14 + version: 8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@mantine/form": - specifier: ^7.17.8 - version: 7.17.8(react@19.2.4) + specifier: ^8.3.14 + version: 8.3.14(react@19.2.4) "@mantine/hooks": - specifier: ^7.17.8 - version: 7.17.8(react@19.2.4) + specifier: ^8.3.14 + version: 8.3.14(react@19.2.4) "@tabler/icons-react": specifier: ^3.36.1 version: 3.36.1(react@19.2.4) "@vercel/analytics": specifier: ^1.6.1 - version: 1.6.1(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) + version: 1.6.1(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) "@vercel/postgres": specifier: ^0.10.0 version: 0.10.0 "@vercel/speed-insights": specifier: ^1.3.1 - version: 1.3.1(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) + version: 1.3.1(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) bcrypt: specifier: ^6.0.0 version: 6.0.0 dotenv: specifier: ^17.2.3 version: 17.2.3 - eslint: - specifier: ^9.39.2 - version: 9.39.2 next: - specifier: ^15.5.10 - version: 15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^16.1.6 + version: 16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next-auth: specifier: 5.0.0-beta.30 - version: 5.0.0-beta.30(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) + version: 5.0.0-beta.30(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) react: specifier: ^19.2.4 version: 19.2.4 @@ -62,33 +59,60 @@ importers: specifier: ^4.3.6 version: 4.3.6 devDependencies: + "@eslint/js": + specifier: ^9.39.2 + version: 9.39.2 + "@next/eslint-plugin-next": + specifier: 16.1.6 + version: 16.1.6 "@playwright/test": - specifier: ^1.58.0 - version: 1.58.0 + specifier: ^1.58.1 + version: 1.58.1 "@types/bcrypt": specifier: ^6.0.0 version: 6.0.0 "@types/node": - specifier: ^24.10.9 - version: 24.10.9 + specifier: ^25.2.0 + version: 25.2.0 "@types/react": - specifier: ^19.2.9 - version: 19.2.9 + specifier: ^19.2.10 + version: 19.2.10 "@types/react-dom": specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.9) + version: 19.2.3(@types/react@19.2.10) + "@typescript-eslint/eslint-plugin": + specifier: ^8.54.0 + version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + "@typescript-eslint/parser": + specifier: ^8.54.0 + version: 8.54.0(eslint@9.39.2)(typescript@5.9.3) + eslint: + specifier: ^9.39.2 + version: 9.39.2 eslint-config-next: - specifier: 15.5.4 - version: 15.5.4(eslint@9.39.2)(typescript@5.9.3) + specifier: 16.1.6 + version: 16.1.6(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) eslint-config-prettier: specifier: ^10.1.8 version: 10.1.8(eslint@9.39.2) + eslint-plugin-jsx-a11y: + specifier: 6.10.2 + version: 6.10.2(eslint@9.39.2) + eslint-plugin-next: + specifier: ^0.0.0 + version: 0.0.0 + eslint-plugin-react: + specifier: 7.37.5 + version: 7.37.5(eslint@9.39.2) + eslint-plugin-react-hooks: + specifier: 7.0.1 + version: 7.0.1(eslint@9.39.2) husky: specifier: ^9.1.7 version: 9.1.7 lint-staged: - specifier: ^15.5.2 - version: 15.5.2 + specifier: ^16.2.7 + version: 16.2.7 postcss: specifier: ^8.5.6 version: 8.5.6 @@ -99,11 +123,14 @@ importers: specifier: ^7.0.1 version: 7.0.1(postcss@8.5.6) prettier: - specifier: 3.6.2 - version: 3.6.2 + specifier: 3.8.1 + version: 3.8.1 typescript: specifier: ^5.9.3 version: 5.9.3 + typescript-eslint: + specifier: 8.54.0 + version: 8.54.0(eslint@9.39.2)(typescript@5.9.3) packages: "@auth/core@0.41.0": @@ -123,6 +150,100 @@ packages: nodemailer: optional: true + "@babel/code-frame@7.29.0": + resolution: + { + integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==, + } + engines: { node: ">=6.9.0" } + + "@babel/compat-data@7.29.0": + resolution: + { + integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==, + } + engines: { node: ">=6.9.0" } + + "@babel/core@7.29.0": + resolution: + { + integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==, + } + engines: { node: ">=6.9.0" } + + "@babel/generator@7.29.0": + resolution: + { + integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-compilation-targets@7.28.6": + resolution: + { + integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-globals@7.28.0": + resolution: + { + integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-module-imports@7.28.6": + resolution: + { + integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-module-transforms@7.28.6": + resolution: + { + integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-string-parser@7.27.1": + resolution: + { + integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-validator-identifier@7.28.5": + resolution: + { + integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-validator-option@7.27.1": + resolution: + { + integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, + } + engines: { node: ">=6.9.0" } + + "@babel/helpers@7.28.6": + resolution: + { + integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==, + } + engines: { node: ">=6.9.0" } + + "@babel/parser@7.29.0": + resolution: + { + integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==, + } + engines: { node: ">=6.0.0" } + hasBin: true + "@babel/runtime@7.28.6": resolution: { @@ -130,6 +251,27 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/template@7.28.6": + resolution: + { + integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, + } + engines: { node: ">=6.9.0" } + + "@babel/traverse@7.29.0": + resolution: + { + integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==, + } + engines: { node: ">=6.9.0" } + + "@babel/types@7.29.0": + resolution: + { + integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==, + } + engines: { node: ">=6.9.0" } + "@emnapi/core@1.8.1": resolution: { @@ -213,35 +355,35 @@ packages: } engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - "@floating-ui/core@1.7.3": + "@floating-ui/core@1.7.4": resolution: { - integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==, + integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==, } - "@floating-ui/dom@1.7.4": + "@floating-ui/dom@1.7.5": resolution: { - integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==, + integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==, } - "@floating-ui/react-dom@2.1.6": + "@floating-ui/react-dom@2.1.7": resolution: { - integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==, + integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==, } peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - "@floating-ui/react@0.26.28": + "@floating-ui/react@0.27.17": resolution: { - integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==, + integrity: sha512-LGVZKHwmWGg6MRHjLLgsfyaX2y2aCNgnD1zT/E6B+/h+vxg+nIJUqHPAlTzsHDyqdgEpJ1Np5kxWuFEErXzoGg==, } peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" + react: ">=17.0.0" + react-dom: ">=17.0.0" "@floating-ui/utils@0.2.10": resolution: @@ -505,28 +647,59 @@ packages: cpu: [x64] os: [win32] - "@mantine/core@7.17.8": + "@jridgewell/gen-mapping@0.3.13": resolution: { - integrity: sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==, + integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, + } + + "@jridgewell/remapping@2.3.5": + resolution: + { + integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, + } + + "@jridgewell/resolve-uri@3.1.2": + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/sourcemap-codec@1.5.5": + resolution: + { + integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, + } + + "@jridgewell/trace-mapping@0.3.31": + resolution: + { + integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, + } + + "@mantine/core@8.3.14": + resolution: + { + integrity: sha512-ZOxggx65Av1Ii1NrckCuqzluRpmmG+8DyEw24wDom3rmwsPg9UV+0le2QTyI5Eo60LzPfUju1KuEPiUzNABIPg==, } peerDependencies: - "@mantine/hooks": 7.17.8 + "@mantine/hooks": 8.3.14 react: ^18.x || ^19.x react-dom: ^18.x || ^19.x - "@mantine/form@7.17.8": + "@mantine/form@8.3.14": resolution: { - integrity: sha512-cRLAMYOsZT17jyV9Myl29xacgaswGVAz3Ku6bvphBFad7Nzorra809uKFJxm2yKW5NknZ4ENHSXjyru7k0GTGA==, + integrity: sha512-LJUeab+oF+YzATrm/K03Z/QoVVYlaolWqLUZZj7XexNA4hS2/ycKyWT07YhGkdHTLXkf3DUtrg1sS77K7Oje8A==, } peerDependencies: react: ^18.x || ^19.x - "@mantine/hooks@7.17.8": + "@mantine/hooks@8.3.14": resolution: { - integrity: sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==, + integrity: sha512-0SbHnGEuHcF2QyjzBBcqidpjNmIb6n7TC3obnhkBToYhUTbMcJSK/8ei/yHtAelridJH4CPeohRlQdc0HajHyQ==, } peerDependencies: react: ^18.x || ^19.x @@ -543,89 +716,89 @@ packages: integrity: sha512-siFas6gItqv6wD/pZnvdu34wEqgG3nSE6zWZdq5j2DEsa+VvX8i/5HXJOo06qrw5axPXn+lGCxeR+NLaSPIXug==, } - "@next/env@15.5.10": + "@next/env@16.1.6": resolution: { - integrity: sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==, + integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==, } - "@next/eslint-plugin-next@15.5.4": + "@next/eslint-plugin-next@16.1.6": resolution: { - integrity: sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==, + integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==, } - "@next/swc-darwin-arm64@15.5.7": + "@next/swc-darwin-arm64@16.1.6": resolution: { - integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==, + integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==, } engines: { node: ">= 10" } cpu: [arm64] os: [darwin] - "@next/swc-darwin-x64@15.5.7": + "@next/swc-darwin-x64@16.1.6": resolution: { - integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==, + integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==, } engines: { node: ">= 10" } cpu: [x64] os: [darwin] - "@next/swc-linux-arm64-gnu@15.5.7": + "@next/swc-linux-arm64-gnu@16.1.6": resolution: { - integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==, + integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] libc: [glibc] - "@next/swc-linux-arm64-musl@15.5.7": + "@next/swc-linux-arm64-musl@16.1.6": resolution: { - integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==, + integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==, } engines: { node: ">= 10" } cpu: [arm64] os: [linux] libc: [musl] - "@next/swc-linux-x64-gnu@15.5.7": + "@next/swc-linux-x64-gnu@16.1.6": resolution: { - integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==, + integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] libc: [glibc] - "@next/swc-linux-x64-musl@15.5.7": + "@next/swc-linux-x64-musl@16.1.6": resolution: { - integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==, + integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==, } engines: { node: ">= 10" } cpu: [x64] os: [linux] libc: [musl] - "@next/swc-win32-arm64-msvc@15.5.7": + "@next/swc-win32-arm64-msvc@16.1.6": resolution: { - integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==, + integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==, } engines: { node: ">= 10" } cpu: [arm64] os: [win32] - "@next/swc-win32-x64-msvc@15.5.7": + "@next/swc-win32-x64-msvc@16.1.6": resolution: { - integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==, + integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==, } engines: { node: ">= 10" } cpu: [x64] @@ -665,10 +838,10 @@ packages: integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==, } - "@playwright/test@1.58.0": + "@playwright/test@1.58.1": resolution: { - integrity: sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==, + integrity: sha512-6LdVIUERWxQMmUSSQi0I53GgCBYgM2RpGngCPY7hSeju+VrKjq3lvs7HpJoPbDiY5QM5EYRtRX5fvrinnMAz3w==, } engines: { node: ">=18" } hasBin: true @@ -679,12 +852,6 @@ packages: integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==, } - "@rushstack/eslint-patch@1.15.0": - resolution: - { - integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==, - } - "@swc/helpers@0.5.15": resolution: { @@ -735,10 +902,10 @@ packages: integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, } - "@types/node@24.10.9": + "@types/node@25.2.0": resolution: { - integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==, + integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==, } "@types/pg@8.11.6": @@ -755,10 +922,10 @@ packages: peerDependencies: "@types/react": ^19.2.0 - "@types/react@19.2.9": + "@types/react@19.2.10": resolution: { - integrity: sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==, + integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==, } "@typescript-eslint/eslint-plugin@8.54.0": @@ -1232,6 +1399,13 @@ packages: integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, } + baseline-browser-mapping@2.9.19: + resolution: + { + integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==, + } + hasBin: true + bcrypt@6.0.0: resolution: { @@ -1258,6 +1432,14 @@ packages: } engines: { node: ">=8" } + browserslist@4.28.1: + resolution: + { + integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + bufferutil@4.1.0: resolution: { @@ -1300,10 +1482,10 @@ packages: } engines: { node: ">= 6" } - caniuse-lite@1.0.30001766: + caniuse-lite@1.0.30001767: resolution: { - integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==, + integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==, } chalk@4.1.2: @@ -1313,13 +1495,6 @@ packages: } engines: { node: ">=10" } - chalk@5.6.2: - resolution: - { - integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, - } - engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } - cli-cursor@5.0.0: resolution: { @@ -1327,12 +1502,12 @@ packages: } engines: { node: ">=18" } - cli-truncate@4.0.0: + cli-truncate@5.1.1: resolution: { - integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==, + integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==, } - engines: { node: ">=18" } + engines: { node: ">=20" } client-only@0.0.1: resolution: @@ -1366,12 +1541,12 @@ packages: integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, } - commander@13.1.0: + commander@14.0.3: resolution: { - integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==, + integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==, } - engines: { node: ">=18" } + engines: { node: ">=20" } concat-map@0.0.1: resolution: @@ -1379,6 +1554,12 @@ packages: integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, } + convert-source-map@2.0.0: + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, + } + cross-spawn@7.0.6: resolution: { @@ -1504,6 +1685,12 @@ packages: } engines: { node: ">= 0.4" } + electron-to-chromium@1.5.283: + resolution: + { + integrity: sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==, + } + emoji-regex@10.6.0: resolution: { @@ -1579,6 +1766,13 @@ packages: } engines: { node: ">= 0.4" } + escalade@3.2.0: + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, + } + engines: { node: ">=6" } + escape-string-regexp@4.0.0: resolution: { @@ -1586,13 +1780,13 @@ packages: } engines: { node: ">=10" } - eslint-config-next@15.5.4: + eslint-config-next@16.1.6: resolution: { - integrity: sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==, + integrity: sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==, } peerDependencies: - eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 + eslint: ">=9.0.0" typescript: ">=3.3.1" peerDependenciesMeta: typescript: @@ -1675,12 +1869,18 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-react-hooks@5.2.0: + eslint-plugin-next@0.0.0: resolution: { - integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==, + integrity: sha512-IldNDVb6WNduggwRbYzSGZhaskUwVecJ6fhmqwX01+S1aohwAWNzU4me6y47DDzpD/g0fdayNBGxEdt9vKkUtg==, } - engines: { node: ">=10" } + + eslint-plugin-react-hooks@7.0.1: + resolution: + { + integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==, + } + engines: { node: ">=18" } peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 @@ -1768,13 +1968,6 @@ packages: integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, } - execa@8.0.1: - resolution: - { - integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==, - } - engines: { node: ">=16.17" } - fast-deep-equal@3.1.3: resolution: { @@ -1893,6 +2086,13 @@ packages: } engines: { node: ">= 0.4" } + gensync@1.0.0-beta.2: + resolution: + { + integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, + } + engines: { node: ">=6.9.0" } + get-east-asian-width@1.4.0: resolution: { @@ -1921,13 +2121,6 @@ packages: } engines: { node: ">= 0.4" } - get-stream@8.0.1: - resolution: - { - integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==, - } - engines: { node: ">=16" } - get-symbol-description@1.1.0: resolution: { @@ -1935,10 +2128,10 @@ packages: } engines: { node: ">= 0.4" } - get-tsconfig@4.13.0: + get-tsconfig@4.13.1: resolution: { - integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==, + integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==, } glob-parent@5.1.2: @@ -1962,6 +2155,13 @@ packages: } engines: { node: ">=18" } + globals@16.4.0: + resolution: + { + integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==, + } + engines: { node: ">=18" } + globalthis@1.0.4: resolution: { @@ -2024,12 +2224,17 @@ packages: } engines: { node: ">= 0.4" } - human-signals@5.0.0: + hermes-estree@0.25.1: + resolution: + { + integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==, + } + + hermes-parser@0.25.1: resolution: { - integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==, + integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==, } - engines: { node: ">=16.17.0" } husky@9.1.7: resolution: @@ -2150,13 +2355,6 @@ packages: } engines: { node: ">= 0.4" } - is-fullwidth-code-point@4.0.0: - resolution: - { - integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==, - } - engines: { node: ">=12" } - is-fullwidth-code-point@5.1.0: resolution: { @@ -2227,13 +2425,6 @@ packages: } engines: { node: ">= 0.4" } - is-stream@3.0.0: - resolution: - { - integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - is-string@1.1.1: resolution: { @@ -2314,6 +2505,14 @@ packages: } hasBin: true + jsesc@3.1.0: + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, + } + engines: { node: ">=6" } + hasBin: true + json-buffer@3.0.1: resolution: { @@ -2339,6 +2538,14 @@ packages: } hasBin: true + json5@2.2.3: + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, + } + engines: { node: ">=6" } + hasBin: true + jsx-ast-utils@3.3.5: resolution: { @@ -2379,27 +2586,20 @@ packages: } engines: { node: ">= 0.8.0" } - lilconfig@3.1.3: + lint-staged@16.2.7: resolution: { - integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==, + integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==, } - engines: { node: ">=14" } - - lint-staged@15.5.2: - resolution: - { - integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==, - } - engines: { node: ">=18.12.0" } + engines: { node: ">=20.17" } hasBin: true - listr2@8.3.3: + listr2@9.0.5: resolution: { - integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==, + integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==, } - engines: { node: ">=18.0.0" } + engines: { node: ">=20.0.0" } locate-path@6.0.0: resolution: @@ -2428,18 +2628,18 @@ packages: } hasBin: true - math-intrinsics@1.1.0: + lru-cache@5.1.1: resolution: { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, } - engines: { node: ">= 0.4" } - merge-stream@2.0.0: + math-intrinsics@1.1.0: resolution: { - integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, } + engines: { node: ">= 0.4" } merge2@1.4.1: resolution: @@ -2455,13 +2655,6 @@ packages: } engines: { node: ">=8.6" } - mimic-fn@4.0.0: - resolution: - { - integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, - } - engines: { node: ">=12" } - mimic-function@5.0.1: resolution: { @@ -2494,6 +2687,13 @@ packages: integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, } + nano-spawn@2.0.0: + resolution: + { + integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==, + } + engines: { node: ">=20.17" } + nanoid@3.3.11: resolution: { @@ -2535,12 +2735,12 @@ packages: nodemailer: optional: true - next@15.5.10: + next@16.1.6: resolution: { - integrity: sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==, + integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==, } - engines: { node: ^18.18.0 || ^19.8.0 || >= 20.0.0 } + engines: { node: ">=20.9.0" } hasBin: true peerDependencies: "@opentelemetry/api": ^1.1.0 @@ -2573,12 +2773,11 @@ packages: } hasBin: true - npm-run-path@5.3.0: + node-releases@2.0.27: resolution: { - integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==, + integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==, } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } oauth4webapi@3.8.3: resolution: @@ -2648,13 +2847,6 @@ packages: integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==, } - onetime@6.0.0: - resolution: - { - integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, - } - engines: { node: ">=12" } - onetime@7.0.0: resolution: { @@ -2711,13 +2903,6 @@ packages: } engines: { node: ">=8" } - path-key@4.0.0: - resolution: - { - integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, - } - engines: { node: ">=12" } - path-parse@1.0.7: resolution: { @@ -2779,18 +2964,18 @@ packages: engines: { node: ">=0.10" } hasBin: true - playwright-core@1.58.0: + playwright-core@1.58.1: resolution: { - integrity: sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==, + integrity: sha512-bcWzOaTxcW+VOOGBCQgnaKToLJ65d6AqfLVKEWvexyS3AS6rbXl+xdpYRMGSRBClPvyj44njOWoxjNdL/H9UNg==, } engines: { node: ">=18" } hasBin: true - playwright@1.58.0: + playwright@1.58.1: resolution: { - integrity: sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==, + integrity: sha512-+2uTZHxSCcxjvGc5C891LrS1/NlxglGxzrC4seZiVjcYVQfUa87wBL6rTDqzGjuoWNjnBzRqKmF6zRYGMvQUaQ==, } engines: { node: ">=18" } hasBin: true @@ -2922,10 +3107,10 @@ packages: } engines: { node: ">= 0.8.0" } - prettier@3.6.2: + prettier@3.8.1: resolution: { - integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==, + integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==, } engines: { node: ">=14" } hasBin: true @@ -3222,13 +3407,6 @@ packages: } engines: { node: ">=14" } - slice-ansi@5.0.0: - resolution: - { - integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==, - } - engines: { node: ">=12" } - slice-ansi@7.1.2: resolution: { @@ -3270,6 +3448,13 @@ packages: } engines: { node: ">=18" } + string-width@8.1.1: + resolution: + { + integrity: sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==, + } + engines: { node: ">=20" } + string.prototype.includes@2.0.1: resolution: { @@ -3325,13 +3510,6 @@ packages: } engines: { node: ">=4" } - strip-final-newline@3.0.0: - resolution: - { - integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, - } - engines: { node: ">=12" } - strip-json-comments@3.1.1: resolution: { @@ -3461,6 +3639,16 @@ packages: } engines: { node: ">= 0.4" } + typescript-eslint@8.54.0: + resolution: + { + integrity: sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + typescript@5.9.3: resolution: { @@ -3488,6 +3676,15 @@ packages: integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==, } + update-browserslist-db@1.2.3: + resolution: + { + integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, + } + hasBin: true + peerDependencies: + browserslist: ">= 4.21.0" + uri-js@4.4.1: resolution: { @@ -3634,6 +3831,12 @@ packages: utf-8-validate: optional: true + yallist@3.1.1: + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, + } + yaml@2.8.2: resolution: { @@ -3649,6 +3852,15 @@ packages: } engines: { node: ">=10" } + zod-validation-error@4.0.2: + resolution: + { + integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==, + } + engines: { node: ">=18.0.0" } + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + zod@4.3.6: resolution: { @@ -3664,8 +3876,108 @@ snapshots: preact: 10.24.3 preact-render-to-string: 6.5.11(preact@10.24.3) + "@babel/code-frame@7.29.0": + dependencies: + "@babel/helper-validator-identifier": 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + "@babel/compat-data@7.29.0": {} + + "@babel/core@7.29.0": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/generator": 7.29.0 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helpers": 7.28.6 + "@babel/parser": 7.29.0 + "@babel/template": 7.28.6 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + "@jridgewell/remapping": 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + "@babel/generator@7.29.0": + dependencies: + "@babel/parser": 7.29.0 + "@babel/types": 7.29.0 + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + jsesc: 3.1.0 + + "@babel/helper-compilation-targets@7.28.6": + dependencies: + "@babel/compat-data": 7.29.0 + "@babel/helper-validator-option": 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + "@babel/helper-globals@7.28.0": {} + + "@babel/helper-module-imports@7.28.6": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-imports": 7.28.6 + "@babel/helper-validator-identifier": 7.28.5 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-string-parser@7.27.1": {} + + "@babel/helper-validator-identifier@7.28.5": {} + + "@babel/helper-validator-option@7.27.1": {} + + "@babel/helpers@7.28.6": + dependencies: + "@babel/template": 7.28.6 + "@babel/types": 7.29.0 + + "@babel/parser@7.29.0": + dependencies: + "@babel/types": 7.29.0 + "@babel/runtime@7.28.6": {} + "@babel/template@7.28.6": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/parser": 7.29.0 + "@babel/types": 7.29.0 + + "@babel/traverse@7.29.0": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/generator": 7.29.0 + "@babel/helper-globals": 7.28.0 + "@babel/parser": 7.29.0 + "@babel/template": 7.28.6 + "@babel/types": 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + "@babel/types@7.29.0": + dependencies: + "@babel/helper-string-parser": 7.27.1 + "@babel/helper-validator-identifier": 7.28.5 + "@emnapi/core@1.8.1": dependencies: "@emnapi/wasi-threads": 1.1.0 @@ -3728,24 +4040,24 @@ snapshots: "@eslint/core": 0.17.0 levn: 0.4.1 - "@floating-ui/core@1.7.3": + "@floating-ui/core@1.7.4": dependencies: "@floating-ui/utils": 0.2.10 - "@floating-ui/dom@1.7.4": + "@floating-ui/dom@1.7.5": dependencies: - "@floating-ui/core": 1.7.3 + "@floating-ui/core": 1.7.4 "@floating-ui/utils": 0.2.10 - "@floating-ui/react-dom@2.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": + "@floating-ui/react-dom@2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": dependencies: - "@floating-ui/dom": 1.7.4 + "@floating-ui/dom": 1.7.5 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - "@floating-ui/react@0.26.28(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": + "@floating-ui/react@0.27.17(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": dependencies: - "@floating-ui/react-dom": 2.1.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + "@floating-ui/react-dom": 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@floating-ui/utils": 0.2.10 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -3860,27 +4172,46 @@ snapshots: "@img/sharp-win32-x64@0.34.5": optional: true - "@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@19.2.4))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": + "@jridgewell/gen-mapping@0.3.13": + dependencies: + "@jridgewell/sourcemap-codec": 1.5.5 + "@jridgewell/trace-mapping": 0.3.31 + + "@jridgewell/remapping@2.3.5": dependencies: - "@floating-ui/react": 0.26.28(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - "@mantine/hooks": 7.17.8(react@19.2.4) + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + + "@jridgewell/resolve-uri@3.1.2": {} + + "@jridgewell/sourcemap-codec@1.5.5": {} + + "@jridgewell/trace-mapping@0.3.31": + dependencies: + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.5 + + "@mantine/core@8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)": + dependencies: + "@floating-ui/react": 0.27.17(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + "@mantine/hooks": 8.3.14(react@19.2.4) clsx: 2.1.1 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-number-format: 5.4.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.9)(react@19.2.4) - react-textarea-autosize: 8.5.9(@types/react@19.2.9)(react@19.2.4) + react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.4) + react-textarea-autosize: 8.5.9(@types/react@19.2.10)(react@19.2.4) type-fest: 4.41.0 transitivePeerDependencies: - "@types/react" - "@mantine/form@7.17.8(react@19.2.4)": + "@mantine/form@8.3.14(react@19.2.4)": dependencies: fast-deep-equal: 3.1.3 klona: 2.0.6 react: 19.2.4 - "@mantine/hooks@7.17.8(react@19.2.4)": + "@mantine/hooks@8.3.14(react@19.2.4)": dependencies: react: 19.2.4 @@ -3895,34 +4226,34 @@ snapshots: dependencies: "@types/pg": 8.11.6 - "@next/env@15.5.10": {} + "@next/env@16.1.6": {} - "@next/eslint-plugin-next@15.5.4": + "@next/eslint-plugin-next@16.1.6": dependencies: fast-glob: 3.3.1 - "@next/swc-darwin-arm64@15.5.7": + "@next/swc-darwin-arm64@16.1.6": optional: true - "@next/swc-darwin-x64@15.5.7": + "@next/swc-darwin-x64@16.1.6": optional: true - "@next/swc-linux-arm64-gnu@15.5.7": + "@next/swc-linux-arm64-gnu@16.1.6": optional: true - "@next/swc-linux-arm64-musl@15.5.7": + "@next/swc-linux-arm64-musl@16.1.6": optional: true - "@next/swc-linux-x64-gnu@15.5.7": + "@next/swc-linux-x64-gnu@16.1.6": optional: true - "@next/swc-linux-x64-musl@15.5.7": + "@next/swc-linux-x64-musl@16.1.6": optional: true - "@next/swc-win32-arm64-msvc@15.5.7": + "@next/swc-win32-arm64-msvc@16.1.6": optional: true - "@next/swc-win32-x64-msvc@15.5.7": + "@next/swc-win32-x64-msvc@16.1.6": optional: true "@nodelib/fs.scandir@2.1.5": @@ -3941,14 +4272,12 @@ snapshots: "@panva/hkdf@1.2.1": {} - "@playwright/test@1.58.0": + "@playwright/test@1.58.1": dependencies: - playwright: 1.58.0 + playwright: 1.58.1 "@rtsao/scc@1.1.0": {} - "@rushstack/eslint-patch@1.15.0": {} - "@swc/helpers@0.5.15": dependencies: tslib: 2.8.1 @@ -3967,7 +4296,7 @@ snapshots: "@types/bcrypt@6.0.0": dependencies: - "@types/node": 24.10.9 + "@types/node": 25.2.0 "@types/estree@1.0.8": {} @@ -3975,21 +4304,21 @@ snapshots: "@types/json5@0.0.29": {} - "@types/node@24.10.9": + "@types/node@25.2.0": dependencies: undici-types: 7.16.0 "@types/pg@8.11.6": dependencies: - "@types/node": 24.10.9 + "@types/node": 25.2.0 pg-protocol: 1.11.0 pg-types: 4.1.0 - "@types/react-dom@19.2.3(@types/react@19.2.9)": + "@types/react-dom@19.2.3(@types/react@19.2.10)": dependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - "@types/react@19.2.9": + "@types/react@19.2.10": dependencies: csstype: 3.2.3 @@ -4143,9 +4472,9 @@ snapshots: "@unrs/resolver-binding-win32-x64-msvc@1.11.1": optional: true - "@vercel/analytics@1.6.1(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)": + "@vercel/analytics@1.6.1(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)": optionalDependencies: - next: 15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 "@vercel/postgres@0.10.0": @@ -4156,9 +4485,9 @@ snapshots: transitivePeerDependencies: - utf-8-validate - "@vercel/speed-insights@1.3.1(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)": + "@vercel/speed-insights@1.3.1(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)": optionalDependencies: - next: 15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 acorn-jsx@5.3.2(acorn@8.15.0): @@ -4271,6 +4600,8 @@ snapshots: balanced-match@1.0.2: {} + baseline-browser-mapping@2.9.19: {} + bcrypt@6.0.0: dependencies: node-addon-api: 8.5.0 @@ -4289,6 +4620,14 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001767 + electron-to-chromium: 1.5.283 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + bufferutil@4.1.0: dependencies: node-gyp-build: 4.8.4 @@ -4314,23 +4653,21 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001766: {} + caniuse-lite@1.0.30001767: {} chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.6.2: {} - cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 - cli-truncate@4.0.0: + cli-truncate@5.1.1: dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 + slice-ansi: 7.1.2 + string-width: 8.1.1 client-only@0.0.1: {} @@ -4344,10 +4681,12 @@ snapshots: colorette@2.0.20: {} - commander@13.1.0: {} + commander@14.0.3: {} concat-map@0.0.1: {} + convert-source-map@2.0.0: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4416,6 +4755,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + electron-to-chromium@1.5.283: {} + emoji-regex@10.6.0: {} emoji-regex@9.2.2: {} @@ -4523,24 +4864,26 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + escalade@3.2.0: {} + escape-string-regexp@4.0.0: {} - eslint-config-next@15.5.4(eslint@9.39.2)(typescript@5.9.3): + eslint-config-next@16.1.6(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3): dependencies: - "@next/eslint-plugin-next": 15.5.4 - "@rushstack/eslint-patch": 1.15.0 - "@typescript-eslint/eslint-plugin": 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - "@typescript-eslint/parser": 8.54.0(eslint@9.39.2)(typescript@5.9.3) + "@next/eslint-plugin-next": 16.1.6 eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2) eslint-plugin-react: 7.37.5(eslint@9.39.2) - eslint-plugin-react-hooks: 5.2.0(eslint@9.39.2) + eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2) + globals: 16.4.0 + typescript-eslint: 8.54.0(eslint@9.39.2)(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: + - "@typescript-eslint/parser" - eslint-import-resolver-webpack - eslint-plugin-import-x - supports-color @@ -4562,7 +4905,7 @@ snapshots: "@nolyfill/is-core-module": 1.0.39 debug: 4.4.3 eslint: 9.39.2 - get-tsconfig: 4.13.0 + get-tsconfig: 4.13.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 @@ -4631,9 +4974,18 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.39.2): + eslint-plugin-next@0.0.0: {} + + eslint-plugin-react-hooks@7.0.1(eslint@9.39.2): dependencies: + "@babel/core": 7.29.0 + "@babel/parser": 7.29.0 eslint: 9.39.2 + hermes-parser: 0.25.1 + zod: 4.3.6 + zod-validation-error: 4.0.2(zod@4.3.6) + transitivePeerDependencies: + - supports-color eslint-plugin-react@7.37.5(eslint@9.39.2): dependencies: @@ -4725,18 +5077,6 @@ snapshots: eventemitter3@5.0.4: {} - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - fast-deep-equal@3.1.3: {} fast-glob@3.3.1: @@ -4801,6 +5141,8 @@ snapshots: generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} + get-east-asian-width@1.4.0: {} get-intrinsic@1.3.0: @@ -4823,15 +5165,13 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stream@8.0.1: {} - get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.13.0: + get-tsconfig@4.13.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -4845,6 +5185,8 @@ snapshots: globals@14.0.0: {} + globals@16.4.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -4874,7 +5216,11 @@ snapshots: dependencies: function-bind: 1.1.2 - human-signals@5.0.0: {} + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 husky@9.1.7: {} @@ -4945,8 +5291,6 @@ snapshots: dependencies: call-bound: 1.0.4 - is-fullwidth-code-point@4.0.0: {} - is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.4.0 @@ -4987,8 +5331,6 @@ snapshots: dependencies: call-bound: 1.0.4 - is-stream@3.0.0: {} - is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -5036,6 +5378,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} @@ -5046,6 +5390,8 @@ snapshots: dependencies: minimist: 1.2.8 + json5@2.2.3: {} + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -5070,26 +5416,19 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.1.3: {} - - lint-staged@15.5.2: + lint-staged@16.2.7: dependencies: - chalk: 5.6.2 - commander: 13.1.0 - debug: 4.4.3 - execa: 8.0.1 - lilconfig: 3.1.3 - listr2: 8.3.3 + commander: 14.0.3 + listr2: 9.0.5 micromatch: 4.0.8 + nano-spawn: 2.0.0 pidtree: 0.6.0 string-argv: 0.3.2 yaml: 2.8.2 - transitivePeerDependencies: - - supports-color - listr2@8.3.3: + listr2@9.0.5: dependencies: - cli-truncate: 4.0.0 + cli-truncate: 5.1.1 colorette: 2.0.20 eventemitter3: 5.0.4 log-update: 6.1.0 @@ -5114,9 +5453,11 @@ snapshots: dependencies: js-tokens: 4.0.0 - math-intrinsics@1.1.0: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 - merge-stream@2.0.0: {} + math-intrinsics@1.1.0: {} merge2@1.4.1: {} @@ -5125,8 +5466,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mimic-fn@4.0.0: {} - mimic-function@5.0.1: {} minimatch@3.1.2: @@ -5141,37 +5480,40 @@ snapshots: ms@2.1.3: {} + nano-spawn@2.0.0: {} + nanoid@3.3.11: {} napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} - next-auth@5.0.0-beta.30(next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4): + next-auth@5.0.0-beta.30(next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4): dependencies: "@auth/core": 0.41.0 - next: 15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + next: 16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 - next@15.5.10(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next@16.1.6(@babel/core@7.29.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: - "@next/env": 15.5.10 + "@next/env": 16.1.6 "@swc/helpers": 0.5.15 - caniuse-lite: 1.0.30001766 + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001767 postcss: 8.4.31 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(react@19.2.4) + styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4) optionalDependencies: - "@next/swc-darwin-arm64": 15.5.7 - "@next/swc-darwin-x64": 15.5.7 - "@next/swc-linux-arm64-gnu": 15.5.7 - "@next/swc-linux-arm64-musl": 15.5.7 - "@next/swc-linux-x64-gnu": 15.5.7 - "@next/swc-linux-x64-musl": 15.5.7 - "@next/swc-win32-arm64-msvc": 15.5.7 - "@next/swc-win32-x64-msvc": 15.5.7 - "@playwright/test": 1.58.0 + "@next/swc-darwin-arm64": 16.1.6 + "@next/swc-darwin-x64": 16.1.6 + "@next/swc-linux-arm64-gnu": 16.1.6 + "@next/swc-linux-arm64-musl": 16.1.6 + "@next/swc-linux-x64-gnu": 16.1.6 + "@next/swc-linux-x64-musl": 16.1.6 + "@next/swc-win32-arm64-msvc": 16.1.6 + "@next/swc-win32-x64-msvc": 16.1.6 + "@playwright/test": 1.58.1 sharp: 0.34.5 transitivePeerDependencies: - "@babel/core" @@ -5181,9 +5523,7 @@ snapshots: node-gyp-build@4.8.4: {} - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 + node-releases@2.0.27: {} oauth4webapi@3.8.3: {} @@ -5231,10 +5571,6 @@ snapshots: obuf@1.1.2: {} - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -5270,8 +5606,6 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} pg-int8@1.0.1: {} @@ -5298,11 +5632,11 @@ snapshots: pidtree@0.6.0: {} - playwright-core@1.58.0: {} + playwright-core@1.58.1: {} - playwright@1.58.0: + playwright@1.58.1: dependencies: - playwright-core: 1.58.0 + playwright-core: 1.58.1 optionalDependencies: fsevents: 2.3.2 @@ -5373,7 +5707,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.6.2: {} + prettier@3.8.1: {} prop-types@15.8.1: dependencies: @@ -5401,39 +5735,39 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - react-remove-scroll-bar@2.3.8(@types/react@19.2.9)(react@19.2.4): + react-remove-scroll-bar@2.3.8(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 - react-style-singleton: 2.2.3(@types/react@19.2.9)(react@19.2.4) + react-style-singleton: 2.2.3(@types/react@19.2.10)(react@19.2.4) tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - react-remove-scroll@2.7.2(@types/react@19.2.9)(react@19.2.4): + react-remove-scroll@2.7.2(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.9)(react@19.2.4) - react-style-singleton: 2.2.3(@types/react@19.2.9)(react@19.2.4) + react-remove-scroll-bar: 2.3.8(@types/react@19.2.10)(react@19.2.4) + react-style-singleton: 2.2.3(@types/react@19.2.10)(react@19.2.4) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.9)(react@19.2.4) - use-sidecar: 1.1.3(@types/react@19.2.9)(react@19.2.4) + use-callback-ref: 1.3.3(@types/react@19.2.10)(react@19.2.4) + use-sidecar: 1.1.3(@types/react@19.2.10)(react@19.2.4) optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - react-style-singleton@2.2.3(@types/react@19.2.9)(react@19.2.4): + react-style-singleton@2.2.3(@types/react@19.2.10)(react@19.2.4): dependencies: get-nonce: 1.0.1 react: 19.2.4 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - react-textarea-autosize@8.5.9(@types/react@19.2.9)(react@19.2.4): + react-textarea-autosize@8.5.9(@types/react@19.2.10)(react@19.2.4): dependencies: "@babel/runtime": 7.28.6 react: 19.2.4 - use-composed-ref: 1.4.0(@types/react@19.2.9)(react@19.2.4) - use-latest: 1.3.0(@types/react@19.2.9)(react@19.2.4) + use-composed-ref: 1.4.0(@types/react@19.2.10)(react@19.2.4) + use-latest: 1.3.0(@types/react@19.2.10)(react@19.2.4) transitivePeerDependencies: - "@types/react" @@ -5602,11 +5936,6 @@ snapshots: signal-exit@4.1.0: {} - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 4.0.0 - slice-ansi@7.1.2: dependencies: ansi-styles: 6.2.3 @@ -5629,6 +5958,11 @@ snapshots: get-east-asian-width: 1.4.0 strip-ansi: 7.1.2 + string-width@8.1.1: + dependencies: + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.8 @@ -5685,14 +6019,14 @@ snapshots: strip-bom@3.0.0: {} - strip-final-newline@3.0.0: {} - strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(react@19.2.4): + styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4): dependencies: client-only: 0.0.1 react: 19.2.4 + optionalDependencies: + "@babel/core": 7.29.0 sugarss@5.0.1(postcss@8.5.6): dependencies: @@ -5767,6 +6101,17 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typescript-eslint@8.54.0(eslint@9.39.2)(typescript@5.9.3): + dependencies: + "@typescript-eslint/eslint-plugin": 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + "@typescript-eslint/parser": 8.54.0(eslint@9.39.2)(typescript@5.9.3) + "@typescript-eslint/typescript-estree": 8.54.0(typescript@5.9.3) + "@typescript-eslint/utils": 8.54.0(eslint@9.39.2)(typescript@5.9.3) + eslint: 9.39.2 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + typescript@5.9.3: {} unbox-primitive@1.1.0: @@ -5802,43 +6147,49 @@ snapshots: "@unrs/resolver-binding-win32-ia32-msvc": 1.11.1 "@unrs/resolver-binding-win32-x64-msvc": 1.11.1 + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 - use-callback-ref@1.3.3(@types/react@19.2.9)(react@19.2.4): + use-callback-ref@1.3.3(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - use-composed-ref@1.4.0(@types/react@19.2.9)(react@19.2.4): + use-composed-ref@1.4.0(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - use-isomorphic-layout-effect@1.2.1(@types/react@19.2.9)(react@19.2.4): + use-isomorphic-layout-effect@1.2.1(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - use-latest@1.3.0(@types/react@19.2.9)(react@19.2.4): + use-latest@1.3.0(@types/react@19.2.10)(react@19.2.4): dependencies: react: 19.2.4 - use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.9)(react@19.2.4) + use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.10)(react@19.2.4) optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 - use-sidecar@1.1.3(@types/react@19.2.9)(react@19.2.4): + use-sidecar@1.1.3(@types/react@19.2.10)(react@19.2.4): dependencies: detect-node-es: 1.1.0 react: 19.2.4 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.9 + "@types/react": 19.2.10 util-deprecate@1.0.2: {} @@ -5901,8 +6252,14 @@ snapshots: optionalDependencies: bufferutil: 4.1.0 + yallist@3.1.1: {} + yaml@2.8.2: {} yocto-queue@0.1.0: {} + zod-validation-error@4.0.2(zod@4.3.6): + dependencies: + zod: 4.3.6 + zod@4.3.6: {} diff --git a/src/actions/signOutAction.ts b/src/actions/signOutAction.ts new file mode 100644 index 0000000..7592cc5 --- /dev/null +++ b/src/actions/signOutAction.ts @@ -0,0 +1,7 @@ +"use server"; + +import { signOut } from "@/auth"; + +export async function signOutAction() { + await signOut(); +} diff --git a/src/app/admin/(admin)/page.tsx b/src/app/admin/(admin)/page.tsx index e304e70..7c8c55b 100644 --- a/src/app/admin/(admin)/page.tsx +++ b/src/app/admin/(admin)/page.tsx @@ -1,7 +1,7 @@ import { Button, Title, Group, Space } from "@mantine/core"; import { Metadata } from "next"; import Header from "@/components/header"; -import { signOut } from "@/auth"; +import { SignOutButton } from "@/components/SignOutButton"; import { IconShoppingCart, IconBeach, @@ -72,16 +72,7 @@ export default function Admin() { - - - + ); diff --git a/src/app/admin/chopinliszt/page.tsx b/src/app/admin/chopinliszt/page.tsx index b4beccf..70fd075 100644 --- a/src/app/admin/chopinliszt/page.tsx +++ b/src/app/admin/chopinliszt/page.tsx @@ -13,7 +13,7 @@ const crumbitems = [ { title: "Chopin Liszt", href: "" }, ]; -export default async function ChopinLiszt() { +export default function ChopinLiszt() { return ( <>
diff --git a/src/app/admin/films/add/page.tsx b/src/app/admin/films/add/page.tsx index cee9d01..c49e6fb 100644 --- a/src/app/admin/films/add/page.tsx +++ b/src/app/admin/films/add/page.tsx @@ -7,7 +7,7 @@ export const metadata: Metadata = { title: "Add film", }; -export default async function AddFilm() { +export default function AddFilm() { return ( <>
diff --git a/src/app/admin/whiskyjournal/add/page.tsx b/src/app/admin/whiskyjournal/add/page.tsx index ae18d98..6778def 100644 --- a/src/app/admin/whiskyjournal/add/page.tsx +++ b/src/app/admin/whiskyjournal/add/page.tsx @@ -7,7 +7,7 @@ export const metadata: Metadata = { title: "Add Whisky", }; -export default async function AddWhisky() { +export default function AddWhisky() { return ( <>
diff --git a/src/app/error.tsx b/src/app/error.tsx index a98e3a7..0cfe596 100644 --- a/src/app/error.tsx +++ b/src/app/error.tsx @@ -26,7 +26,9 @@ export default function Error({ + + + ); +} diff --git a/src/components/backtotop.tsx b/src/components/backtotop.tsx index 361fd19..806d46e 100644 --- a/src/components/backtotop.tsx +++ b/src/components/backtotop.tsx @@ -16,7 +16,9 @@ const BackToTop: React.FC = () => { } style={transitionStyles} - onClick={() => scrollTo({ y: 0 })} + onClick={() => { + scrollTo({ y: 0 }); + }} > Back to top diff --git a/src/components/boomboompirate.tsx b/src/components/boomboompirate.tsx index bf421d0..e0efae7 100644 --- a/src/components/boomboompirate.tsx +++ b/src/components/boomboompirate.tsx @@ -36,7 +36,7 @@ const BoomBoomPirate = () => { generateRandomRope(totalRopes), ); const [loadingRope, setLoadingRope] = useState(null); - const [ropeStates, setRopeStates] = useState<{ [key: number]: string }>({}); + const [ropeStates, setRopeStates] = useState>({}); const [isExplosion, setIsExplosion] = useState(false); const [currentIcon, setCurrentIcon] = useState(null); const [showExplosions, setShowExplosions] = useState(false); @@ -129,13 +129,15 @@ const BoomBoomPirate = () => { ))} @@ -170,13 +172,16 @@ const BoomBoomPirate = () => { {showExplosions && ( <> - {[...Array(3)].map((_, i) => { + {Array.from({ length: 3 }).map((_, i) => { const { top, left } = generateRandomPosition(); return (
); })} diff --git a/src/components/carddeck.tsx b/src/components/carddeck.tsx index 76b7fbd..4ccbbcc 100644 --- a/src/components/carddeck.tsx +++ b/src/components/carddeck.tsx @@ -15,10 +15,10 @@ export const RankNames = [ "Two", ]; -export type Card = { +export interface Card { suit: string; rank: string; -}; +} export function getCardName(suit: string, rank: string): string { return `${rank} of ${suit}`; diff --git a/src/components/chopinliszt.tsx b/src/components/chopinliszt.tsx index eb46873..b86e31c 100644 --- a/src/components/chopinliszt.tsx +++ b/src/components/chopinliszt.tsx @@ -33,10 +33,6 @@ const ChopinLiszt: React.FC = () => { const [items, setItems] = useState([]); const [newItemText, setNewItemText] = useState(""); - useEffect(() => { - fetchItems(); - }, []); - const fetchItems = async () => { try { console.log("Requesting new data"); @@ -49,6 +45,20 @@ const ChopinLiszt: React.FC = () => { } }; + useEffect(() => { + void (async () => { + try { + console.log("Requesting new data"); + const data = await readChopin(); + console.log("Data fetch successful"); + setItems(data); + setLoading(false); + } catch (error) { + console.error("Error fetching data:", error); + } + })(); + }, []); + const addItem = async () => { // Split the user input into separate lines for each item const itemsToAdd = newItemText.trim().split("\n"); @@ -117,13 +127,17 @@ const ChopinLiszt: React.FC = () => { data-autofocus placeholder="Add new items, one per line..." value={newItemText} - onChange={(e) => setNewItemText(e.target.value)} + onChange={(e) => { + setNewItemText(e.target.value); + }} autosize minRows={7} /> setModalOpened(false)} + onClose={() => { + setModalOpened(false); + }} title="Confirm Deletion" > ID: {filmData.id} Name: {filmData.name} Are you sure you want to delete this Film? - - diff --git a/src/components/filmlist.tsx b/src/components/filmlist.tsx index b860ea5..942dc42 100644 --- a/src/components/filmlist.tsx +++ b/src/components/filmlist.tsx @@ -37,7 +37,7 @@ export default function FilmList() { } }; - fetchFilms(); + void fetchFilms(); }, []); const [imdbFilter, setImdbFilter] = useState(null); @@ -116,7 +116,7 @@ export default function FilmList() { const copyToClipboard = () => { const filmNameList = searchedFilmData - .map((film) => `${film.name} (${film.release_year})`) + .map((film) => `${film.name} (${film.release_year.toString()})`) .join("\n"); clipboard.copy(filmNameList); }; @@ -158,33 +158,33 @@ export default function FilmList() { label="IMDB top 30" data={imdbOptions} value={imdbFilter !== null ? imdbFilter.toString() : null} - onChange={(value) => + onChange={(value) => { setImdbFilter( value === "true" ? true : value === "false" ? false : null, - ) - } + ); + }} clearable /> + onChange={(value) => { setJarFilter( value === "true" ? true : value === "false" ? false : null, - ) - } + ); + }} clearable /> @@ -192,7 +192,7 @@ export default function FilmList() { label="Sort by" placeholder="Select sorting option" data={sortOptions} - value={sortOption !== null ? sortOption : "alphabetical"} // Default value set to "alphabetical" + value={sortOption ?? "alphabetical"} // Default value set to "alphabetical" onChange={setSortOption} clearable /> @@ -233,7 +233,9 @@ export default function FilmList() { rightSection={ searchQuery && ( setSearchQuery("")} + onClick={() => { + setSearchQuery(""); + }} variant="default" aria-label="Clear search query" > @@ -247,7 +249,9 @@ export default function FilmList() { @@ -242,7 +248,7 @@ export default function IrishBingo() { mt="sm" id="card_count" ta="center" - >{`${drawnCards.length} / 52 cards`} + >{`${drawnCards.length.toString()} / 52 cards`} @@ -353,7 +359,9 @@ export default function WhiskyJournal() { rightSection={ searchQuery && ( setSearchQuery("")} + onClick={() => { + setSearchQuery(""); + }} variant="default" aria-label="Clear search query" > diff --git a/src/components/whiskyjournaledit.tsx b/src/components/whiskyjournaledit.tsx index 8ad6fe6..25aa024 100644 --- a/src/components/whiskyjournaledit.tsx +++ b/src/components/whiskyjournaledit.tsx @@ -87,24 +87,42 @@ export const WhiskyJournalEdit = ({ whiskyData }: { whiskyData: Whisky }) => { Edit Whisky - setModalOpened(false)} + onClose={() => { + setModalOpened(false); + }} title="Confirm Deletion" > Whisky ID: {whiskyData.whisky_id} Name: {whiskyData.name} Are you sure you want to delete this whisky? - - diff --git a/src/middleware.ts b/src/proxy.ts similarity index 100% rename from src/middleware.ts rename to src/proxy.ts diff --git a/src/services/chopinliszt.ts b/src/services/chopinliszt.ts index 992c661..5697ebe 100644 --- a/src/services/chopinliszt.ts +++ b/src/services/chopinliszt.ts @@ -12,14 +12,14 @@ const FormSchema = z.object({ const CreateChopin = FormSchema; -export type State = { +export interface State { errors?: { chopin_id?: string[]; chopin_text?: string[]; checked?: boolean[]; }; message?: string | null; -}; +} export async function createChopin(formData: FormData) { const validatedFields = CreateChopin.safeParse({ @@ -28,7 +28,7 @@ export async function createChopin(formData: FormData) { if (!validatedFields.success) { return { - errors: validatedFields.error.flatten().fieldErrors, + errors: z.treeifyError(validatedFields.error), message: "Missing Fields. Failed to parse chopin_text.", }; } @@ -53,12 +53,16 @@ export async function createChopin(formData: FormData) { export async function readChopin(): Promise { try { - const data = await sql` - SELECT chopin_id, chopin_text, checked - FROM chopin_liszt; - `; + const data = await sql<{ + chopin_id: string; + chopin_text: string; + checked: boolean; + }>` + SELECT chopin_id, chopin_text, checked + FROM chopin_liszt; + `; - const latestChopin = data.rows.map((chopin) => ({ + const latestChopin: Item[] = data.rows.map((chopin) => ({ id: chopin.chopin_id, text: chopin.chopin_text, checked: chopin.checked, diff --git a/src/services/filmlist.ts b/src/services/filmlist.ts index 8abe912..035cd92 100644 --- a/src/services/filmlist.ts +++ b/src/services/filmlist.ts @@ -21,12 +21,12 @@ export async function createFilm(film: Film): Promise { export async function readFilmList(): Promise { try { - const data = await sql` - SELECT id, name, release_year, top_30, watched, not_in_jar - FROM film_list; - `; + const data = await sql` + SELECT id, name, release_year, top_30, watched, not_in_jar + FROM film_list; + `; - const films = data.rows.map((film) => ({ + const films: Film[] = data.rows.map((film) => ({ id: film.id, name: film.name, release_year: film.release_year, @@ -44,11 +44,11 @@ export async function readFilmList(): Promise { export async function readFilm(film_id: string): Promise { try { - const data = await sql` - SELECT id, name, release_year, top_30, watched, not_in_jar - FROM film_list - WHERE id = ${film_id}; - `; + const data = await sql` + SELECT id, name, release_year, top_30, watched, not_in_jar + FROM film_list + WHERE id = ${film_id}; + `; if (data.rows.length > 1) { throw new Error("More than one film found with the given name."); @@ -58,7 +58,7 @@ export async function readFilm(film_id: string): Promise { throw new Error("No film found with the given name."); } - const film = { + const film: Film = { id: data.rows[0].id, name: data.rows[0].name, release_year: data.rows[0].release_year, diff --git a/src/services/whiskyjournal.ts b/src/services/whiskyjournal.ts index 757cf87..67e2e02 100644 --- a/src/services/whiskyjournal.ts +++ b/src/services/whiskyjournal.ts @@ -27,12 +27,12 @@ export async function createWhisky(whisky: Whisky): Promise { // Read all whiskies export async function readWhiskyJournal(): Promise { try { - const data = await sql` - SELECT last_edited, whisky_id, name, distillery, country_region, age, grain, abv, rating, price, notes - FROM whisky_journal; - `; + const data = await sql` + SELECT last_edited, whisky_id, name, distillery, country_region, age, grain, abv, rating, price, notes + FROM whisky_journal; + `; - const whiskies = data.rows.map((whisky) => ({ + const whiskies: Whisky[] = data.rows.map((whisky) => ({ last_edited: whisky.last_edited, whisky_id: whisky.whisky_id, name: whisky.name, @@ -56,11 +56,11 @@ export async function readWhiskyJournal(): Promise { // Read single whisky by id export async function readWhisky(whisky_id: string): Promise { try { - const data = await sql` - SELECT last_edited, whisky_id, name, distillery, country_region, age, grain, abv, rating, price, notes - FROM whisky_journal - WHERE whisky_id = ${whisky_id}; - `; + const data = await sql` + SELECT last_edited, whisky_id, name, distillery, country_region, age, grain, abv, rating, price, notes + FROM whisky_journal + WHERE whisky_id = ${whisky_id}; + `; if (data.rows.length > 1) { throw new Error("More than one whisky found with the given ID."); @@ -70,7 +70,7 @@ export async function readWhisky(whisky_id: string): Promise { throw new Error("No whisky found with the given ID."); } - const whisky = { + const whisky: Whisky = { last_edited: data.rows[0].last_edited, whisky_id: data.rows[0].whisky_id, name: data.rows[0].name, diff --git a/tests/admin/00_admin_pages.spec.ts b/tests/admin/00_admin_pages.spec.ts index 7301691..6d5062f 100644 --- a/tests/admin/00_admin_pages.spec.ts +++ b/tests/admin/00_admin_pages.spec.ts @@ -1,12 +1,13 @@ import { test, expect } from "@playwright/test"; test("Can sign in and navigate admin", async ({ page }) => { - const email = process.env.TEST_EMAIL as string; - const password = process.env.TEST_PASSWORD as string; + const email = process.env.TEST_EMAIL; + const password = process.env.TEST_PASSWORD; if (!email || !password) { - console.error("Missing environment variables: TEST_EMAIL or TEST_PASSWORD"); - process.exit(1); + throw new Error( + "Missing environment variables: TEST_EMAIL or TEST_PASSWORD", + ); } await page.goto("/admin/login"); diff --git a/tests/public-database/01_whiskyjournal.spec.ts b/tests/public-database/01_whiskyjournal.spec.ts index 71963ac..5d594d5 100644 --- a/tests/public-database/01_whiskyjournal.spec.ts +++ b/tests/public-database/01_whiskyjournal.spec.ts @@ -1,4 +1,5 @@ import { test, expect } from "@playwright/test"; +import fs from "fs"; test("Whisky Journal Page Test", async ({ page }) => { await page.goto("/"); @@ -9,6 +10,7 @@ test("Whisky Journal Page Test", async ({ page }) => { // Check the seeded whisky entries are loaded await expect(page.locator("#main-content")).toContainText( /Talisker 10 Year Old/, + { timeout: 10000 }, ); await expect(page.locator("#main-content")).toContainText( /Johnnie Walker Black Label/, @@ -58,7 +60,6 @@ test("Can search whiskies by name", async ({ page }) => { ); }); -const fs = require("fs"); test("Download CSV and check contents", async ({ page }) => { await page.goto("/whiskyjournal"); const [download] = await Promise.all([ @@ -66,9 +67,10 @@ test("Download CSV and check contents", async ({ page }) => { page.getByRole("button", { name: "Download CSV" }).click(), ]); - const path = await download.path(); - const csv = fs.readFileSync(path, "utf-8"); - const rows = csv.split("\n"); + const path: string | null = await download.path(); + if (!path) throw new Error("Download path not found"); + const csv: string = fs.readFileSync(path, "utf-8"); + const rows: string[] = csv.split("\n"); expect(rows.length).toBeGreaterThan(30); }); diff --git a/tests/public-database/02_filmlist.spec.ts b/tests/public-database/02_filmlist.spec.ts index b86c18e..f762e50 100644 --- a/tests/public-database/02_filmlist.spec.ts +++ b/tests/public-database/02_filmlist.spec.ts @@ -1,4 +1,5 @@ import { test, expect } from "@playwright/test"; +import fs from "fs"; test("Films Page Test", async ({ page }) => { await page.goto("/"); @@ -50,7 +51,6 @@ test("Can copy film names to clipboard", async ({ page, context }) => { expect(clipboardText).toContain("Seven Samurai (1954)"); }); -const fs = require("fs"); test("Download CSV and check contents", async ({ page }) => { await page.goto("/films"); const [download] = await Promise.all([ @@ -58,9 +58,10 @@ test("Download CSV and check contents", async ({ page }) => { page.getByRole("button", { name: "Download CSV" }).click(), ]); - const path = await download.path(); - const csv = fs.readFileSync(path, "utf-8"); - const rows = csv.split("\n"); + const path: string | null = await download.path(); + if (!path) throw new Error("Download path not found"); + const csv: string = fs.readFileSync(path, "utf-8"); + const rows: string[] = csv.split("\n"); expect(rows.length).toBeGreaterThan(50); }); diff --git a/tests/public/03_irishbingo.spec.ts b/tests/public/03_irishbingo.spec.ts index 6c96d0e..07fd3b1 100644 --- a/tests/public/03_irishbingo.spec.ts +++ b/tests/public/03_irishbingo.spec.ts @@ -33,7 +33,7 @@ test("Gameplay works", async ({ page }) => { drawnCards.push(drawnCard); await expect(page.locator("#card_count")).toContainText( - `${buttonpress_reindexed} / 52 cards`, + `${String(buttonpress_reindexed)} / 52 cards`, ); } diff --git a/tests/public/04_cocktails.spec.ts b/tests/public/04_cocktails.spec.ts index f17eadb..9099a96 100644 --- a/tests/public/04_cocktails.spec.ts +++ b/tests/public/04_cocktails.spec.ts @@ -9,6 +9,7 @@ test("Can filter and search cocktails", async ({ page }) => { // Filter by gin await page.getByLabel("Filter by base spirit").selectOption("Gin"); + await page.waitForTimeout(4000); await expect(page.locator("text=Manhattan")).not.toBeVisible(); await expect(page.locator("text=Luigi")).toBeVisible(); diff --git a/tsconfig.json b/tsconfig.json index 906e42a..6ea46dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -28,7 +28,8 @@ "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", - "types/**/*.ts" + "types/**/*.ts", + ".next/dev/types/**/*.ts" ], "exclude": ["node_modules"] } diff --git a/types/index.d.ts b/types/index.d.ts index 2bf1fa8..753d7f2 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -2,6 +2,6 @@ export {}; declare global { interface Window { - ConfettiPage: any; + ConfettiPage: unknown; } }