diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 002e016..9f87523 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,8 +1,4 @@ /* eslint-env node */ -require("@typescript-eslint/eslint-recommended"); -require("@typescript-eslint/parser"); -require("eslint-plugin-solid"); - module.exports = { root: true, parser: "@typescript-eslint/parser", @@ -16,53 +12,44 @@ module.exports = { { files: ["**/*.tsx"], parserOptions: { - ecmaFeatures: { - jsx: true, - }, + ecmaFeatures: { jsx: true }, }, settings: { - solid: { - // SolidJS specific options - noImportReact: true, - }, + solid: { noImportReact: true }, }, rules: { - "solid/hyperscript": "off", "solid/jsx-no-undef": "error", - "solid/jsx-pseudo-element": "error", - "solid/jsx-single-root-elem": "error", - "solid/no-dynamic-mount": "error", - "solid/no-hyphen-in-props": "error", - "solid/no-leaked-event-handlers": "error", - "solid/no-react-unknown-property": "error", - "solid/no-unknown-property": "error", - "solid/no-useless-fragment": "error", - "solid/prefer-classlist": "error", - "solid/prefer-destructuring": "warn", - "solid/prefer-innerhtml": "warn", + "solid/prefer-classlist": "off", + "solid/prefer-for": "error", + "solid/reactivity": "warn", + "solid/event-handlers": "off", + "solid/no-react-specific-props": "off", + "solid/no-innerhtml": "warn", + "solid/no-destructure": "warn", + "solid/self-closing-comp": "off", + // Admin codebase uses inline string styles throughout — suppress style-prop noise + "solid/style-prop": "off", }, }, ], rules: { "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], - "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_", varsIgnorePattern: "^_", destructuredArrayIgnorePattern: "^_" }], + "@typescript-eslint/no-explicit-any": "off", "arrow-body-style": ["warn", "as-needed"], - " curly": ["error", "multi-line"], + curly: ["error", "multi-line"], "no-console": "off", "no-debugger": "warn", "no-unused-vars": "off", "prefer-const": "error", }, - env: { - browser: true, - }, + env: { browser: true }, ignorePatterns: [ "dist", ".output", "node_modules", "coverage", + "storybook-static", "test-results", - "playwright-report", ], }; diff --git a/package-lock.json b/package-lock.json index 12991fb..cc23cb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,12 @@ "@testing-library/jest-dom": "^6.6.3", "@types/node": "^26.1.1", "@types/pngjs": "^6.0.5", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "@vitest/browser-playwright": "^4.1.1", "@vitest/coverage-v8": "^4.1.1", + "eslint": "^8.57.1", + "eslint-plugin-solid": "^0.14.5", "jsdom": "^25.0.1", "msw": "^2.7.3", "pixelmatch": "^7.1.0", @@ -50,7 +54,7 @@ "version": "4.4.4", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@asamuzakjp/css-color": { @@ -618,6 +622,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -634,6 +639,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -650,6 +656,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -666,6 +673,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -682,6 +690,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -698,6 +707,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -714,6 +724,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -730,6 +741,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -746,6 +758,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -762,6 +775,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -778,6 +792,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -794,6 +809,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -810,6 +826,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -826,6 +843,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -842,6 +860,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -858,6 +877,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -874,6 +894,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -890,6 +911,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -906,6 +928,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -922,6 +945,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -938,6 +962,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -954,6 +979,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -970,6 +996,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -986,6 +1013,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1002,6 +1030,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1018,6 +1047,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1027,6 +1057,179 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@inquirer/ansi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", @@ -3073,7 +3276,7 @@ "version": "6.9.1", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@adobe/css-tools": "^4.4.0", @@ -3093,7 +3296,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@testing-library/user-event": { @@ -3249,7 +3452,7 @@ "version": "26.1.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~8.3.0" @@ -3259,7 +3462,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/pngjs": { @@ -3272,17 +3475,6 @@ "@types/node": "*" } }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "csstype": "^3.2.2" - } - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -3302,6 +3494,296 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -3758,6 +4240,23 @@ "node": ">= 14" } }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -3993,16 +4492,33 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "dequal": "^2.0.3" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -4524,6 +5040,16 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", @@ -4911,6 +5437,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/confbox": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", @@ -5050,7 +5583,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/cssstyle": { @@ -5210,6 +5743,13 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -5349,6 +5889,32 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -5560,6 +6126,7 @@ "version": "0.27.4", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -5624,6 +6191,279 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-solid": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-solid/-/eslint-plugin-solid-0.14.5.tgz", + "integrity": "sha512-nfuYK09ah5aJG/oEN6P1qziy1zLgW4PDWe75VNPi4CEFYk1x2AEqwFeQfEPR7gNn0F2jOeqKhx2E+5oNCOBYWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^7.13.1 || ^8.0.0", + "estraverse": "^5.3.0", + "is-html": "^2.0.0", + "kebab-case": "^1.0.2", + "known-css-properties": "^0.30.0", + "style-to-object": "^1.0.6" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=4.8.4" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5637,12 +6477,58 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -5724,6 +6610,13 @@ "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", "license": "MIT" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -5746,6 +6639,20 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -5772,6 +6679,19 @@ } } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -5800,6 +6720,45 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -5885,6 +6844,13 @@ "node": ">= 0.6" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -6033,6 +6999,35 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globby": { "version": "16.2.2", "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.2.tgz", @@ -6072,6 +7067,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/graphql": { "version": "16.13.2", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.2.tgz", @@ -6246,6 +7248,19 @@ "dev": true, "license": "MIT" }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/html-to-image": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", @@ -6390,22 +7405,78 @@ "node": ">= 4" } }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "dev": true, + "license": "MIT" + }, "node_modules/ioredis": { "version": "5.11.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", @@ -6497,6 +7568,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-html": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-html/-/is-html-2.0.0.tgz", + "integrity": "sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "html-tags": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-in-ssh": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", @@ -6728,6 +7812,29 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsdom": { "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", @@ -6818,6 +7925,27 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -6843,6 +7971,23 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/kebab-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz", + "integrity": "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -6867,6 +8012,13 @@ "integrity": "sha512-4LqMNoONzR43B1W0ek0fhXMsDNW/zxa1NdFAVMY+k28pgZLovR4G3PB5MrpTxCy1QaZCqNoiaKPr5w5qZHfSNw==", "license": "MIT" }, + "node_modules/known-css-properties": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", + "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -6909,6 +8061,20 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -7324,12 +8490,35 @@ "pathe": "^2.0.3" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -7645,7 +8834,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -7837,6 +9026,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/nitropack": { "version": "2.13.4", "resolved": "https://registry.npmjs.org/nitropack/-/nitropack-2.13.4.tgz", @@ -8736,6 +9932,16 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -8798,6 +10004,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -8805,12 +10029,57 @@ "dev": true, "license": "MIT" }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", @@ -8832,6 +10101,26 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8878,6 +10167,16 @@ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -9045,6 +10344,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-bytes": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-7.1.0.tgz", @@ -9316,7 +10625,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "indent-string": "^4.0.0", @@ -9434,6 +10743,76 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/rollup": { "version": "4.62.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", @@ -10231,7 +11610,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "min-indent": "^1.0.0" @@ -10240,6 +11619,19 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", @@ -10258,6 +11650,16 @@ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "license": "MIT" }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/supports-color": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", @@ -10420,6 +11822,13 @@ "b4a": "^1.6.4" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -10568,6 +11977,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-dedent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", @@ -10584,6 +12006,19 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -11190,6 +12625,16 @@ "integrity": "sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA==", "license": "MIT" }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -11827,6 +13272,7 @@ "version": "7.3.6", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", @@ -12170,6 +13616,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", @@ -12261,6 +13717,13 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, "node_modules/ws": { "version": "8.21.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", @@ -12405,6 +13868,19 @@ "node": ">=8" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yoctocolors-cjs": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", diff --git a/package.json b/package.json index b09cbd3..d7afeec 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", "qa:visbug": "bash ./scripts/visbug-storybook.sh", - "qa:e2e:blueprint": "bash ./scripts/run-nxtgauge-e2e-suite.sh" + "qa:e2e:blueprint": "bash ./scripts/run-nxtgauge-e2e-suite.sh", + "lint": "eslint src --ext .tsx,.ts --max-warnings 0" }, "dependencies": { "@solidjs/meta": "^0.29.4", @@ -54,8 +55,12 @@ "@testing-library/jest-dom": "^6.6.3", "@types/node": "^26.1.1", "@types/pngjs": "^6.0.5", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "@vitest/browser-playwright": "^4.1.1", "@vitest/coverage-v8": "^4.1.1", + "eslint": "^8.57.1", + "eslint-plugin-solid": "^0.14.5", "jsdom": "^25.0.1", "msw": "^2.7.3", "pixelmatch": "^7.1.0", diff --git a/src/components/AdminShell.tsx b/src/components/AdminShell.tsx index fa0712a..629399f 100644 --- a/src/components/AdminShell.tsx +++ b/src/components/AdminShell.tsx @@ -9,7 +9,7 @@ import { onMount, type JSX, } from "solid-js"; -import { Bell, Moon, Search, Settings, Sun, User } from "lucide-solid"; +import { Bell, Moon, Search, Settings, Sun } from "lucide-solid"; import AdminSidebar from "./AdminSidebar"; import { isExternalIdentity } from "~/lib/admin-auth"; import { normalizeAllowedModules } from "~/lib/admin/module-access"; @@ -218,7 +218,7 @@ function extractList(data: any, keys: string[]): any[] { return []; } -function GlobalSearch() { +function _GlobalSearch() { const [query, setQuery] = createSignal(""); const [open, setOpen] = createSignal(false); const [groups, setGroups] = createSignal([]); @@ -355,7 +355,7 @@ function GlobalSearch() { ); } -function ShowTabs(props: { +function _ShowTabs(props: { tabs: Tab[]; isTabActive: (tab: Tab) => boolean; setTabsTrackEl: (el: HTMLDivElement) => void; @@ -364,8 +364,8 @@ function ShowTabs(props: { ) => void; tabIndicator: () => { left: number; width: number; ready: boolean }; }) { - if (props.tabs.length === 0) return null; return ( + 0}>
+
); } export default function AdminShell(props: { children: JSX.Element }) { const location = useLocation(); const navigate = useNavigate(); - const [searchParams] = useSearchParams(); + const [_searchParams] = useSearchParams(); const [checkedSession, setCheckedSession] = createSignal(true); const [adminName, setAdminName] = createSignal("Admin User"); @@ -406,12 +407,13 @@ export default function AdminShell(props: { children: JSX.Element }) { const [sidebarOpen, setSidebarOpen] = createSignal(false); const [sidebarCollapsed, setSidebarCollapsed] = createSignal(false); const [unreadCount, setUnreadCount] = createSignal(0); + const [pendingVerificationCount, setPendingVerificationCount] = createSignal(0); const [theme, setTheme] = createSignal<"light" | "dark">("light"); - const [routeTransitioning, setRouteTransitioning] = createSignal(false); + const [routeTransitioning, _setRouteTransitioning] = createSignal(false); - const [tabsTrackEl, setTabsTrackEl] = createSignal(); - const [tabRefs, setTabRefs] = createSignal>({}); - const [tabIndicator, setTabIndicator] = createSignal({ left: 0, width: 0, ready: false }); + const [tabsTrackEl, _setTabsTrackEl] = createSignal(); + const [tabRefs, _setTabRefs] = createSignal>({}); + const [_tabIndicator, _setTabIndicator] = createSignal({ left: 0, width: 0, ready: false }); let contentScrollRef: HTMLDivElement | undefined; const logout = async () => { @@ -482,7 +484,6 @@ export default function AdminShell(props: { children: JSX.Element }) { sessionStorage.removeItem("nxtgauge_admin_access_token"); sessionStorage.removeItem("nxtgauge_admin_preview"); } - clearAdminSession(); navigate(`/login?from=${encodeURIComponent(location.pathname + location.search)}`, { replace: true, }); @@ -534,6 +535,36 @@ export default function AdminShell(props: { children: JSX.Element }) { const interval = setInterval(fetchUnreadCount, 30000); onCleanup(() => clearInterval(interval)); + // Fetch pending-verification count and poll every 60 s so the sidebar badge + // stays up-to-date as users submit role registrations. + const fetchPendingVerificationCount = async () => { + try { + const accessToken = + typeof sessionStorage !== "undefined" + ? sessionStorage.getItem("nxtgauge_admin_access_token") || "" + : ""; + if (!accessToken) return; + const res = await fetch("/api/admin/verifications?status=PENDING&limit=200", { + headers: { + Accept: "application/json", + ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}), + }, + credentials: "include", + }); + if (res.ok) { + const data = await res.json().catch(() => ({})); + const items = Array.isArray(data?.items) ? data.items : []; + setPendingVerificationCount(items.length); + } + } catch { + // non-fatal — badge stays at its last value + } + }; + + fetchPendingVerificationCount(); + const verificationPoll = setInterval(fetchPendingVerificationCount, 60000); + onCleanup(() => clearInterval(verificationPoll)); + const verify = async () => { // The server-verified session check below (/api/auth/session) is the // real security boundary. It redirects to /login on any failure. @@ -601,7 +632,7 @@ export default function AdminShell(props: { children: JSX.Element }) { void verify(); }); - const pageTitle = createMemo(() => { + const _pageTitle = createMemo(() => { const path = location.pathname; for (const entry of PAGE_TITLES) { if ( @@ -736,6 +767,7 @@ export default function AdminShell(props: { children: JSX.Element }) { theme={theme()} allowedModules={allowedModules()} isSuperAdmin={isSuperAdmin()} + badgeCounts={{ pendingVerifications: pendingVerificationCount() }} /> diff --git a/src/components/AdminSidebar.tsx b/src/components/AdminSidebar.tsx index f0c4540..7a308e6 100644 --- a/src/components/AdminSidebar.tsx +++ b/src/components/AdminSidebar.tsx @@ -6,7 +6,6 @@ import { Briefcase, Users, ShieldCheck, - FileText, LayoutDashboard, ClipboardList, UserRoundSearch, @@ -43,9 +42,12 @@ import { type NavItem = { href: string; label: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any icon: any; aliasPrefix?: string; moduleKeys?: string[]; + /** Optional badge key — used to look up count from badgeCounts prop */ + badgeKey?: string; }; const GROUPS: NavItem[][] = [ @@ -120,6 +122,7 @@ const GROUPS: NavItem[][] = [ label: "Verification Management", icon: BadgeCheck, moduleKeys: ["VERIFICATION_MANAGEMENT", "VERIFICATIONS"], + badgeKey: "pendingVerifications", }, { href: "/admin/approval", @@ -339,12 +342,6 @@ const GROUPS: NavItem[][] = [ icon: Receipt, moduleKeys: ["LEDGER", "LEDGER_MANAGEMENT"], }, - { - href: "/admin/ai-management", - label: "AI Management", - icon: Sparkles, - moduleKeys: ["AI_MANAGEMENT", "AI"], - }, ], ]; @@ -357,6 +354,8 @@ export default function AdminSidebar(props: { theme?: "light" | "dark"; allowedModules?: string[] | null; isSuperAdmin?: boolean; + /** Map of badgeKey → count; a non-zero count shows an orange pill on the nav item */ + badgeCounts?: Record; }) { const location = useLocation(); @@ -438,7 +437,7 @@ export default function AdminSidebar(props: { - ))} + )}
- {spec.packages.map((pkg, i) => ( + {(pkg, getI) => { const i = getI(); return (
Most Chosen @@ -2258,14 +2258,14 @@ export default function DashboardDesignPreview(props: {

{pkg.name}

{pkg.price}

- {pkg.items.map((item) => ( + {(item) => (
{item}
- ))} + )}
- ))} + ); }}
@@ -2303,12 +2303,12 @@ export default function DashboardDesignPreview(props: { } >
- {[0,1,2,3,4,5].map((i) => ( + {(i) => (
{mediaConfig.items[i % mediaConfig.items.length]}
- ))} + )}
@@ -2329,9 +2329,9 @@ export default function DashboardDesignPreview(props: {

{spec.equipmentLabel}

- {spec.specialties.map((item) => ( + {(item) => ( {item} - ))} + )}

Design Tools

@@ -2339,9 +2339,9 @@ export default function DashboardDesignPreview(props: { when={canEdit} fallback={
- {(portfolioDesignTools().length ? portfolioDesignTools() : portfolioTools).map((tool) => ( + {(tool) => ( {tool} - ))} + )}
} > @@ -2350,24 +2350,24 @@ export default function DashboardDesignPreview(props: {
- {(portfolioDesignTools().length ? portfolioDesignTools() : portfolioTools).map((tool) => ( + {(tool) => ( {tool} - ))} + )}
- {[['2018','Started professional career as '+spec.roleLabel],['2020','Completed 100+ successful projects'],['2022','Won regional industry recognition'],['2024','Joined Nxtgauge marketplace']].map(([yr, desc], i, arr) => ( -
+ {([yr, desc], getI) => { const i = getI(); return ( +

{yr}

{desc}

- ))} + ); }}
@@ -2399,18 +2399,18 @@ export default function DashboardDesignPreview(props: { } >
- {PORTFOLIO_TESTIMONIALS.map((t, i) => ( + {(t) => (

{t.name}

- {Array.from({length: t.rating}).map(() => )} + {() => }

{t.category}

{t.text}

- ))} + )}
@@ -2547,17 +2547,17 @@ if (tab === 'quick actions') {

Quick Actions

- {quickActionsByRole.map((a, i) => ( + {(a, getI) => { const i = getI(); return ( - ))} + ); }}

Recent Activity

- {activityByRole.map((a) =>
{a}
)} + {(a) =>
{a}
}
@@ -2840,11 +2840,11 @@ return (
- {[ + ( + ]}>{([key, title]) => (

{title}

- ))} + )}
- {[ + ( + ]}>{([key, title]) => (

{title}

- ))} + )}

Delete Account

@@ -3095,17 +3095,17 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{(card) => (

{card.label}

{card.value}

- ))} + )}
@@ -3180,12 +3180,12 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{(step, getIdx) => { const idx = getIdx(); return ( <> - + - ))} + ); }}

Resume & Portfolio

Showcase your best work and professional journey to the hiring team.

@@ -3279,16 +3279,16 @@ if (customerKey() === 'leads') {

{selectedJob().company} • Design Team

- {[ + ( + ]}>{([label, val]) => (

{label}

{val}

- ))} + )}

The Opportunity

@@ -3297,11 +3297,11 @@ if (customerKey() === 'leads') {

Core Requirements

- {[ +

• {item}

)} + ]}>{(item) =>

• {item}

}
@@ -3322,25 +3322,25 @@ if (customerKey() === 'leads') { return (
- {[ + ( + ]}>{(card) => (

{card.label}

{card.value}

- ))} + )}
- {['Role: All Roles', 'Industry: Tech', 'Location: Remote', 'Salary: $100k+', 'Experience: Senior'].map((item) => ( + {(item) => ( - ))} + )}
@@ -3352,9 +3352,9 @@ if (customerKey() === 'leads') {

{job.title}

{job.company} • {job.location}

- {[job.salary, job.exp, job.type].map((pill, idx) => ( + {(pill, getIdx) => { const idx = getIdx(); return ( {pill} - ))} + ); }}
{(tag) => {tag}} @@ -3432,12 +3432,12 @@ if (customerKey() === 'leads') { REF: #JX-9902
- {[ + ( + ]}>{(row, getIdx) => { const idx = getIdx(); return (
{row.done ? '✓' : idx + 1}
@@ -3445,7 +3445,7 @@ if (customerKey() === 'leads') {

{row.desc}

- ))} + ); }}
@@ -3487,17 +3487,17 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{([label, value]) => (

{label}

{value}

- ))} + )}
@@ -3607,7 +3607,7 @@ if (customerKey() === 'leads') {

Job Title

e.g. Senior Full Stack Engineer

Department

Select Department

Job Category

Select Category
-

Employment Type

{['Full Time', 'Part Time', 'Internship'].map((type, idx) => {type})}
+

Employment Type

{(type, getIdx) => { const idx = getIdx(); return {type}; }}

Seniority

Entry Level

Openings

1

Description

Detailed job responsibilities, skills, and expectations...
@@ -3631,16 +3631,16 @@ if (customerKey() === 'leads') {

Position

Product Design Manager

- {[ + ( + ]}>{([label, val]) => (
{label} {val}
- ))} + )}
@@ -3678,17 +3678,17 @@ if (customerKey() === 'leads') { return (
- {[ + ( + ]}>{(card, getIdx) => { const idx = getIdx(); return (

{card.label}

{card.value}

- ))} + ); }}
@@ -3771,17 +3771,17 @@ if (customerKey() === 'leads') { return (
- {[ + row.status === 'Under Review').length) }, { label: 'Shortlisted', value: String(JOB_SEEKER_APPLIED_ROWS.filter((row) => row.status === 'Shortlisted').length) }, { label: 'Rejected', value: String(JOB_SEEKER_APPLIED_ROWS.filter((row) => row.status === 'Not Selected').length) }, - ].map((card) => ( + ]}>{(card) => (

{card.label}

{card.value}

- ))} + )}
@@ -3966,14 +3966,14 @@ if (customerKey() === 'leads') {

Basic Requirement Details

Add core details before role-specific inputs.

- {['Requirement Title', 'Priority', 'Requirement Description', 'Expected Start Date', 'Service City', 'Contact Number'].map((field) => ( + {(field) => (

{field}

Enter {field.toLowerCase()}
- ))} + )}
@@ -4028,7 +4028,7 @@ if (customerKey() === 'leads') {

Budget & Location

Set your target budget and service location to get relevant quotes.

- {['Budget Range', 'Urgency Level', 'Service Location', 'Mode (Remote / On-site)', 'Preferred Start Date', 'Flexible Budget'].map((field, idx) => ( + {(field, getIdx) => { const idx = getIdx(); return (

{field}

@@ -4036,7 +4036,7 @@ if (customerKey() === 'leads') {
- ))} + ); }}
@@ -4046,12 +4046,12 @@ if (customerKey() === 'leads') {

Attachments

Upload reference files to help professionals understand your requirement better.

- {[1, 2, 3, 4].map((slot) => ( + {(slot) => (
+

Attachment {slot}

- ))} + )}
@@ -4062,18 +4062,18 @@ if (customerKey() === 'leads') {

Review & Submit

Final check before submitting for approval.

- {[ + ( + ]}>{([label, value]) => (
{label} {value}
- ))} + )}
@@ -4081,12 +4081,12 @@ if (customerKey() === 'leads') {

Submit For Approval

Once submitted, your requirement goes to review and then becomes visible to matching professionals.

- {['Draft Created', 'Submitted', 'Under Review', 'Approved'].map((state, idx) => ( + {(state, getIdx) => { const idx = getIdx(); return (
{idx < 2 ? '✓' : idx + 1} {state}
- ))} + ); }}
@@ -4133,16 +4133,16 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{([label, val]) => (

{label}

{val}

- ))} + )}
@@ -4160,11 +4160,11 @@ if (customerKey() === 'leads') {

Reference Material

- {[1, 2, 3, 4].map((slot) => ( + {(slot) => (
{slot === 4 ? 'Add More' : `Asset ${slot}`}
- ))} + )}
@@ -4182,7 +4182,7 @@ if (customerKey() === 'leads') {

Approval History

- {['Requirement Approved', 'Under Review', 'Submitted', 'Draft Created'].map((step) => ( + {(step) => (
@@ -4190,13 +4190,13 @@ if (customerKey() === 'leads') {

Oct 24, 2023

- ))} + )}
- {['Extend Expiry', 'Edit Details', 'Close Requirement'].map((action, idx) => ( + {(action, getIdx) => { const idx = getIdx(); return ( - ))} + ); }}
@@ -4226,42 +4226,42 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{([label, value], getIdx) => { const idx = getIdx(); return (

{label}

{value}

- ))} + ); }}
- {['All Requirements', 'Drafts', 'Submitted', 'Approved', 'Active', 'Rejected', 'Closed', 'Expired'].map((label, idx) => ( + {(label, getIdx) => { const idx = getIdx(); return ( - ))} + ); }}
Search ID or Title...
- {['Sort By: Newest', 'Category: All', 'Status: All'].map((item) => ( + {(item) => ( - ))} + )}
- {['ID', 'Requirement Details', 'Category', 'Budget & Location', 'Submission', 'Status', 'Actions'].map((head) => ( + {(head) => ( - ))} + )} @@ -4307,7 +4307,7 @@ if (customerKey() === 'leads') {

Showing 1 to {Math.min(filteredRows.length, 6)} of {filteredRows.length} requirements

- {[1, 2, 3].map((p) => )} + {(p) => }
@@ -4403,11 +4403,11 @@ if (customerKey() === 'leads') {
- {['Newest First', 'Oldest First'].map((item) => ( + {(item) => ( - ))} + )}
@@ -4418,11 +4418,11 @@ if (customerKey() === 'leads') {
- {['All Status', 'Request Sent', 'Contact Unlocked', 'Rejected', 'Expired Refunded', 'Cancelled By Professional'].map((item) => ( + {(item) => ( - ))} + )}
@@ -4441,9 +4441,9 @@ if (customerKey() === 'leads') {
{head}
- {['Lead ID', 'Lead Title', 'Request Date', 'Status', 'Cost', 'Decision Date', 'Action'].map((h) => ( + {(h) => ( - ))} + )} @@ -4616,12 +4616,12 @@ if (customerKey() === 'leads') {
- {[ + ( + ]}>{(pkg) => (
@@ -4644,7 +4644,7 @@ if (customerKey() === 'leads') {
- ))} + )}
@@ -4701,13 +4701,13 @@ if (customerKey() === 'leads') {
{h}
- {['Invoice No', 'Package', 'Credits', 'Amount Paid', 'Status', 'Date', 'Actions'].map((h) => ( + {(h) => ( - ))} + )} - {txRows.map((row) => ( + {(row) => ( @@ -4724,15 +4724,15 @@ if (customerKey() === 'leads') { - ))} + )}
{h}
{row[0]} {row[1]}

Showing 1 to 4 of 42 transactions

- {[1, 2, 3].map((p) => ( + {(p) => ( - ))} + )}
@@ -4769,18 +4769,18 @@ if (customerKey() === 'leads') { - {['Usage ID', 'Action Type', 'Credits Used', 'Related ID', 'Date', 'Remarks'].map((h) => ( + {(h) => ( - ))} + )} - {[ + ( + ]}>{(row) => ( @@ -4789,15 +4789,15 @@ if (customerKey() === 'leads') { - ))} + )}
{h}
{row[0]} {row[1]}{row[4]} {row[5]}

Showing 1 to 4 of 142 results

- {[1, 2, 3].map((p) => ( + {(p) => ( - ))} + )}
@@ -4828,13 +4828,13 @@ if (customerKey() === 'leads') { - {['Invoice Number', 'Billing Date', 'Package', 'Total', 'Status'].map((h) => ( + {(h) => ( - ))} + )} - {invoiceRows.map((row) => ( + {(row) => ( @@ -4844,15 +4844,15 @@ if (customerKey() === 'leads') { {row[4]} - ))} + )}
{h}
{row[0]} {row[1]}

Showing 1 to 4 of 24 invoices

- {[1, 2, 3].map((p) => ( + {(p) => ( - ))} + )}
@@ -4912,13 +4912,13 @@ if (customerKey() === 'leads') { - {['Transaction ID', 'Package', 'Credits', 'Amount Paid', 'Status', 'Date'].map((h) => ( + {(h) => ( - ))} + )} - {txRows.slice(0, 3).map((row) => ( + {(row) => ( @@ -4929,7 +4929,7 @@ if (customerKey() === 'leads') { - ))} + )}
{h}
{row[0]} {row[1]} {row[5]}
@@ -4946,11 +4946,11 @@ if (customerKey() === 'leads') {
- {[ + { + ]}>{(roleCard) => { const isCurrentRole = normalizeRoleKey(props.roleKey || '') === normalizeRoleKey(roleCard.key); return (
@@ -4965,7 +4965,7 @@ if (customerKey() === 'leads') {
); - })} + }}
@@ -5076,14 +5076,14 @@ if (customerKey() === 'leads') {

Application Snapshot

- {[ + ( + ]}>{([k, v]) => (
{k}: {v}
- ))} + )}
@@ -5092,7 +5092,7 @@ if (customerKey() === 'leads') { Strategic Social Media Manager with 6+ years of experience in content strategy, campaign planning, and audience growth for D2C brands.
- {['Sprout Social', 'Figma', 'Google Analytics'].map((tool) => {tool})} + {(tool) => {tool}}
@@ -5139,11 +5139,11 @@ if (customerKey() === 'leads') { - {[ + ( + ]}>{([doc, file, state]) => ( {doc} {file} @@ -5159,7 +5159,7 @@ if (customerKey() === 'leads') {
- ))} + )} @@ -5195,12 +5195,12 @@ if (customerKey() === 'leads') {

Verification Updates

- {[ + ( + ]}>{([time, title, state]) => (

{title}

@@ -5208,7 +5208,7 @@ if (customerKey() === 'leads') {
{state}
- ))} + )}
); @@ -5245,7 +5245,7 @@ if (customerKey() === 'leads') {
Popular: - {['Account Access', 'Verification', 'Hiring Fees'].map((tag) => {tag})} + {(tag) => {tag}}
@@ -5302,11 +5302,11 @@ if (customerKey() === 'leads') { Actionable tutorials to master Nxtgauge
- {[ + ( + ]}>{(g) => (
{g.level} @@ -5323,7 +5323,7 @@ if (customerKey() === 'leads') {
- ))} + )} @@ -5360,7 +5360,7 @@ if (customerKey() === 'leads') { - {HELP_TICKET_ROWS.map((t) => ( + {(t) => ( openTicketDetails(t.id)} style={`border-top:1px solid #F3F4F6;background:${activeTicketId() === t.id ? '#F5F7FF' : 'white'};cursor:pointer`}> {t.id} {t.title} @@ -5382,7 +5382,7 @@ if (customerKey() === 'leads') { - ))} + )} @@ -5509,24 +5509,24 @@ if (customerKey() === 'leads') { if (customerKey() === 'settings') { if (tab === 'privacy') { - return
{['Profile visibility', 'Data sharing consent', 'Session management'].map((s) =>
{s}Enabled
)}
; + return
{(s) =>
{s}Enabled
}
; } if (tab === 'notifications') { - return
{['Response alerts', 'Billing alerts', 'Security alerts'].map((s) =>
{s}On
)}
; + return
{(s) =>
{s}On
}
; } - return
{['Change Password', 'Two-factor authentication', 'Login activity'].map((s) =>
{s}
)}
; + return
{(s) =>
{s}
}
; } if (customerKey() === 'switch role' || customerKey() === 'switch services' || customerKey() === 'switch service') { if (tab === 'pending approvals') { - return
{['Professional - Under Review', 'Company - Documents Pending'].map((r) =>
{r}
)}
; + return
{(r) =>
{r}
}
; } if (tab === 'approved services') { - return
{['Service Seeker - Approved', 'Photographer - Approved', 'Company - Approved'].map((r) =>
{r}
)}
; + return
{(r) =>
{r}
}
; } return (
- {['Service Seeker (Active)', 'Professional', 'Company'].map((r, i) =>

{r}

)} + {(r, getI) => { const i = getI(); return

{r}

; }}
); } diff --git a/src/components/admin/UserListPage.tsx b/src/components/admin/UserListPage.tsx index 2491b48..d9ab974 100644 --- a/src/components/admin/UserListPage.tsx +++ b/src/components/admin/UserListPage.tsx @@ -107,12 +107,12 @@ export default function UserListPage(props: { config: UserListPageConfig }) { {/* Stat cards */}
- {([ + stats().total, Ic: Users, bg: 'bg-[#FFF1EB]', color: 'text-[#FF5E13]' }, { label: 'Active', value: () => stats().active, Ic: UserCheck, bg: 'bg-[#ECFDF5]', color: 'text-[#059669]' }, { label: 'Inactive', value: () => stats().inactive, Ic: UserX, bg: 'bg-[#FEF2F2]', color: 'text-[#DC2626]' }, { label: 'Pending Verification', value: () => stats().pending, Ic: Clock, bg: 'bg-[#FFFBEB]', color: 'text-[#D97706]' }, - ] as const).map(s => ( + ]}>{(s) => (
@@ -124,7 +124,7 @@ export default function UserListPage(props: { config: UserListPageConfig }) {
- ))} + )}
{/* Table card */} diff --git a/src/routes/about.tsx b/src/routes/about.tsx deleted file mode 100644 index c1c2dcf..0000000 --- a/src/routes/about.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Title } from "@solidjs/meta"; - -export default function About() { - return ( -
- About -

About

-
- ); -} diff --git a/src/routes/admin/approval-management.tsx b/src/routes/admin/approval-management.tsx deleted file mode 100644 index 3755e57..0000000 --- a/src/routes/admin/approval-management.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Navigate } from '@solidjs/router'; - -export default function ApprovalManagementLegacyRedirectPage() { - return ; -} diff --git a/src/routes/admin/approval/index.tsx b/src/routes/admin/approval/index.tsx index fdbda2d..da55711 100644 --- a/src/routes/admin/approval/index.tsx +++ b/src/routes/admin/approval/index.tsx @@ -483,11 +483,11 @@ export default function ApprovalManagementPage() {
- {([ + { setListTab('all'); setStatusFilter('all'); } }, { key: 'escalated', label: `Escalated (${escalatedCount()})`, action: () => { setListTab('escalated'); setStatusFilter('escalated'); } }, { key: 'view', label: 'View Approval', action: () => { setListTab('view'); } }, - ] as const).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
@@ -523,8 +523,9 @@ export default function ApprovalManagementPage() {
- {(['overview', 'verification', 'checklist', 'logs'] as const).map((tab, i) => { + {(tab, getI) => { const labels = ['Overview', 'Verification Summary', 'Approval Checklist', 'Activity Logs']; + const i = getI(); const active = () => detailTab() === tab; return ( ); - })} + }}
@@ -612,18 +613,18 @@ export default function ApprovalManagementPage() {
- {[ + ( + ]}>{(item) => ( - ))} + )}
@@ -674,11 +675,14 @@ export default function ApprovalManagementPage() {
- {(['submitted_desc', 'submitted_asc', 'priority_desc', 'priority_asc'] as const).map((s, i) => ( - - ))} + {(s, getI) => { + const i = getI(); + return ( + + ); + }}
@@ -693,11 +697,11 @@ export default function ApprovalManagementPage() {
- {(['all', 'pending', 'escalated'] as const).map((s) => ( + {(s) => ( - ))} + )}
diff --git a/src/routes/admin/approvals.tsx b/src/routes/admin/approvals.tsx deleted file mode 100644 index 632b4ca..0000000 --- a/src/routes/admin/approvals.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Navigate } from '@solidjs/router'; - -export default function ApprovalsLegacyRedirectPage() { - return ; -} diff --git a/src/routes/admin/candidate.tsx b/src/routes/admin/candidate.tsx index 45d13ec..5a22122 100644 --- a/src/routes/admin/candidate.tsx +++ b/src/routes/admin/candidate.tsx @@ -121,12 +121,12 @@ export default function CandidateManagementPage() {
{/* Tabs */}
- {([ + { setListTab('all'); setStatusFilter('all'); } }, { key: 'active', label: 'Active', action: () => { setListTab('active'); setStatusFilter('active'); } }, { key: 'pending', label: 'Pending', action: () => { setListTab('pending'); setStatusFilter('pending'); } }, { key: 'view', label: 'View Profile', action: () => setListTab('view') }, - ] as const).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
{/* View Profile panel */} @@ -158,8 +158,9 @@ export default function CandidateManagementPage() {
- {(['overview', 'experience', 'skills'] as const).map((tab, i) => { + {(tab, getI) => { const labels = ['Overview', 'Work Experience', 'Skills & Education']; + const i = getI(); const active = () => detailTab() === tab; return ( ); - })} + }}
@@ -176,17 +177,17 @@ export default function CandidateManagementPage() {

Candidate Info

- {[ + ( + ]}>{(item) => (
{item.l} {item.v}
- ))} + )}
@@ -221,11 +222,14 @@ export default function CandidateManagementPage() {
- {(['name_asc', 'name_desc', 'registered_desc', 'registered_asc'] as const).map((s, i) => ( - - ))} + {(s, getI) => { + const i = getI(); + return ( + + ); + }}
@@ -240,11 +244,11 @@ export default function CandidateManagementPage() {
- {(['all', 'active', 'pending', 'inactive'] as const).map((s) => ( + {(s) => ( - ))} + )}
@@ -262,9 +266,9 @@ export default function CandidateManagementPage() { - {['Candidate Name', 'Email', 'Location', 'Registered', 'Status', 'Actions'].map(h => ( + {(h) => ( - ))} + )} diff --git a/src/routes/admin/company/index.tsx b/src/routes/admin/company/index.tsx index 3e86f2a..41ef61c 100644 --- a/src/routes/admin/company/index.tsx +++ b/src/routes/admin/company/index.tsx @@ -177,12 +177,12 @@ export default function CompanyManagementPage() {
- {([ + { setListTab('all'); setStatusFilter('all'); } }, { key: 'active', label: 'Active', action: () => { setListTab('active'); setStatusFilter('ACTIVE'); } }, { key: 'pending', label: 'Pending', action: () => { setListTab('pending'); setStatusFilter('PENDING'); } }, { key: 'view', label: 'View Company', action: () => setListTab('view') }, - ] as const).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
@@ -212,8 +212,9 @@ export default function CompanyManagementPage() {
- {(['overview', 'verification', 'metrics'] as const).map((tab, i) => { + {(tab, getI) => { const labels = ['Overview', 'Verification', 'Metrics']; + const i = getI(); const active = () => detailTab() === tab; return ( ); - })} + }}
@@ -230,17 +231,17 @@ export default function CompanyManagementPage() {

Company Profile

- {[ + ( + ]}>{(item) => (
{item.l} {item.v || '—'}
- ))} + )}
@@ -251,16 +252,16 @@ export default function CompanyManagementPage() {

Verification Summary

- {[ + ( + ]}>{(item) => (
{item.l} {item.v || '—'}
- ))} + )}
@@ -271,15 +272,15 @@ export default function CompanyManagementPage() {

Performance Metrics

- {[ + ( + ]}>{(item) => (
{item.l} {item.v}
- ))} + )}
@@ -318,12 +319,12 @@ export default function CompanyManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -353,13 +354,13 @@ export default function CompanyManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -384,9 +385,9 @@ export default function CompanyManagementPage() {
{h}
- {['Company', 'Industry', 'Location', 'Status', 'Joined', 'Actions'].map((h) => ( + {(h) => ( - ))} + )} diff --git a/src/routes/admin/coupon.tsx b/src/routes/admin/coupon.tsx index a25df23..dcafafd 100644 --- a/src/routes/admin/coupon.tsx +++ b/src/routes/admin/coupon.tsx @@ -101,9 +101,9 @@ export default function CouponPage() { let r = coupons(); const q = search().toLowerCase(); if (q) - r = r.filter( + {r = r.filter( (c) => c.code.toLowerCase().includes(q) || (c.title || "").toLowerCase().includes(q) - ); + );} if (statusFilter() === "active") r = r.filter((c) => c.is_active); if (statusFilter() === "inactive") r = r.filter((c) => !c.is_active); const sorted = [...r]; diff --git a/src/routes/admin/credit.tsx b/src/routes/admin/credit.tsx index 1c49384..82add9b 100644 --- a/src/routes/admin/credit.tsx +++ b/src/routes/admin/credit.tsx @@ -619,7 +619,7 @@ export default function CreditPage() {
{/* AI Credits Sub-tabs */}
- {(['balance', 'adjust', 'reconcile'] as const).map((t) => ( + {(t) => ( - ))} + )}
{/* AI Balance & Ledger */} diff --git a/src/routes/admin/customer.tsx b/src/routes/admin/customer.tsx index 69d7fbe..220a0d4 100644 --- a/src/routes/admin/customer.tsx +++ b/src/routes/admin/customer.tsx @@ -120,12 +120,12 @@ export default function CustomerManagementPage() {
{/* Tabs */}
- {([ + { setListTab('all'); setStatusFilter('all'); } }, { key: 'active', label: 'Active', action: () => { setListTab('active'); setStatusFilter('active'); } }, { key: 'pending', label: 'Pending', action: () => { setListTab('pending'); setStatusFilter('pending'); } }, { key: 'view', label: 'View Profile', action: () => setListTab('view') }, - ] as const).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
{/* View Profile panel */} @@ -157,7 +157,8 @@ export default function CustomerManagementPage() {
- {(['overview', 'orders', 'support'] as const).map((tab, i) => { + {(tab, getI) => { + const i = getI(); const labels = ['Overview', 'Order History', 'Support Cases']; const active = () => detailTab() === tab; return ( @@ -166,7 +167,7 @@ export default function CustomerManagementPage() { ); - })} + }}
@@ -175,17 +176,17 @@ export default function CustomerManagementPage() {

Customer Summary

- {[ + ( + ]}>{item => (
{item.l} {item.v}
- ))} + )}
@@ -220,11 +221,14 @@ export default function CustomerManagementPage() {
- {(['name_asc', 'name_desc', 'orders_desc', 'orders_asc'] as const).map((s, i) => ( - - ))} + {(s, getI) => { + const i = getI(); + return ( + + ); + }}
@@ -239,11 +243,11 @@ export default function CustomerManagementPage() {
- {(['all', 'active', 'pending', 'inactive'] as const).map((s) => ( + {(s) => ( - ))} + )}
@@ -261,9 +265,9 @@ export default function CustomerManagementPage() {
{h}
- {['Customer Name', 'Email', 'Location', 'Orders', 'Status', 'Actions'].map(h => ( + {h => ( - ))} + )} diff --git a/src/routes/admin/department-management.tsx b/src/routes/admin/department-management.tsx deleted file mode 100644 index c08db3e..0000000 --- a/src/routes/admin/department-management.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import DepartmentManagementPage from './department'; - -export default DepartmentManagementPage; diff --git a/src/routes/admin/department.tsx b/src/routes/admin/department.tsx index a34576f..931a211 100644 --- a/src/routes/admin/department.tsx +++ b/src/routes/admin/department.tsx @@ -164,9 +164,9 @@ export default function DepartmentManagementPage() { sorted.sort((a, b) => { if (mode === "name_desc") return b.name.localeCompare(a.name); if (mode === "employees_desc") - return Number(b.totalEmployees || 0) - Number(a.totalEmployees || 0); + {return Number(b.totalEmployees || 0) - Number(a.totalEmployees || 0);} if (mode === "employees_asc") - return Number(a.totalEmployees || 0) - Number(b.totalEmployees || 0); + {return Number(a.totalEmployees || 0) - Number(b.totalEmployees || 0);} return a.name.localeCompare(b.name); }); r = sorted; @@ -266,8 +266,7 @@ export default function DepartmentManagementPage() {
{/* Tabs */}
- {( - [ + setListTab("view") }, - ] as const - ).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
{/* View Department panel */} @@ -409,8 +407,9 @@ export default function DepartmentManagementPage() {
- {(["name_asc", "name_desc", "employees_desc", "employees_asc"] as const).map( - (s, i) => ( + {(s, getI) => { + const i = getI(); + return ( - ) - )} + ); + }}
@@ -456,7 +455,7 @@ export default function DepartmentManagementPage() {
- {(["all", "active", "inactive"] as const).map((s) => ( + {(s) => ( - ))} + )}
@@ -647,7 +646,7 @@ export default function DepartmentManagementPage() { } ); if (!res.ok) - throw new Error(`Request failed (${res.status})`); + {throw new Error(`Request failed (${res.status})`);} } catch (err: any) { setError(err?.message || "Failed to update status."); } finally { @@ -822,7 +821,8 @@ export default function DepartmentManagementPage() {
{/* Sub-tabs */}
- {(["general", "settings"] as const).map((tab, i) => { + {(tab, getI) => { + const i = getI(); const labels = ["General Information", "Department Settings"]; const active = () => formTab() === tab; return ( @@ -837,7 +837,7 @@ export default function DepartmentManagementPage() { ); - })} + }}
@@ -879,7 +879,7 @@ export default function DepartmentManagementPage() { Set whether this department is currently active

- {(["ACTIVE", "INACTIVE"] as const).map((s) => ( + {(s) => ( - ))} + )}
diff --git a/src/routes/admin/designation-management.tsx b/src/routes/admin/designation-management.tsx deleted file mode 100644 index fe40cb1..0000000 --- a/src/routes/admin/designation-management.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import Designation from "./designation"; -export default Designation; diff --git a/src/routes/admin/designation.tsx b/src/routes/admin/designation.tsx index 7fefe32..0c79eec 100644 --- a/src/routes/admin/designation.tsx +++ b/src/routes/admin/designation.tsx @@ -247,9 +247,9 @@ export default function DesignationManagementPage() { sorted.sort((a, b) => { if (mode === "name_desc") return b.name.localeCompare(a.name); if (mode === "employees_desc") - return Number(b.totalEmployees || 0) - Number(a.totalEmployees || 0); + {return Number(b.totalEmployees || 0) - Number(a.totalEmployees || 0);} if (mode === "employees_asc") - return Number(a.totalEmployees || 0) - Number(b.totalEmployees || 0); + {return Number(a.totalEmployees || 0) - Number(b.totalEmployees || 0);} return a.name.localeCompare(b.name); }); r = sorted; @@ -386,8 +386,7 @@ export default function DesignationManagementPage() {
{/* Tabs */}
- {( - [ + setListTab("view") }, - ] as const - ).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
{/* View Record panel */} @@ -538,8 +536,9 @@ export default function DesignationManagementPage() {
- {(["name_asc", "name_desc", "employees_desc", "employees_asc"] as const).map( - (s, i) => ( + {(s, getI) => { + const i = getI(); + return ( - ) - )} + ); + }}
@@ -588,7 +587,7 @@ export default function DesignationManagementPage() {

Status

- {(["all", "active", "inactive"] as const).map((s) => ( + {(s) => ( - ))} + )}

Department @@ -802,7 +801,7 @@ export default function DesignationManagementPage() { } ); if (!res.ok) - throw new Error(`Request failed (${res.status})`); + {throw new Error(`Request failed (${res.status})`);} } catch (err: any) { setError(err?.message || "Failed to update status."); } finally { @@ -971,7 +970,8 @@ export default function DesignationManagementPage() {

{/* Sub-tabs */}
- {(["general", "settings"] as const).map((tab, i) => { + {(tab, getI) => { + const i = getI(); const labels = ["General Information", "Designation Settings"]; const active = () => formTab() === tab; return ( @@ -986,7 +986,7 @@ export default function DesignationManagementPage() { ); - })} + }}
@@ -1034,7 +1034,7 @@ export default function DesignationManagementPage() { Set whether this designation is currently active

- {(["ACTIVE", "INACTIVE"] as const).map((s) => ( + {(s) => ( - ))} + )}
diff --git a/src/routes/admin/employees/index.tsx b/src/routes/admin/employees/index.tsx index e39f153..923df20 100644 --- a/src/routes/admin/employees/index.tsx +++ b/src/routes/admin/employees/index.tsx @@ -568,8 +568,8 @@ export default function EmployeeManagementPage() { {/* Tabs */}
- {( - [ + ( - - ))} + ] as const} + > + {(tab) => ( + + )} +
@@ -640,18 +642,23 @@ export default function EmployeeManagementPage() {
- {(["joined_desc", "joined_asc", "name_asc", "name_desc"] as const).map((s, i) => ( - - ))} + + {(s, getI) => { + const i = getI(); + return ( + + ); + }} +
@@ -678,20 +685,24 @@ export default function EmployeeManagementPage() {
- {( - ["all", "ACTIVE", "PROBATION", "ON_LEAVE", "SUSPENDED", "INACTIVE"] as const - ).map((s) => ( - - ))} + + {(s) => ( + + )} +
@@ -832,7 +843,7 @@ export default function EmployeeManagementPage() { type="button" onClick={async () => { if (!confirm(`Are you sure you want to delete ${row.name}?`)) - return; + {return;} setOpenMenuId(null); try { const accessToken = @@ -897,22 +908,25 @@ export default function EmployeeManagementPage() {
- {(["basic", "work", "access"] as const).map((tab, i) => { - const labels = ["Basic Information", "Work Information", "Access & Permissions"]; - const active = () => formTab() === tab; - return ( - - ); - })} + + {(tab, getI) => { + const labels = ["Basic Information", "Work Information", "Access & Permissions"]; + const i = getI(); + const active = () => formTab() === tab; + return ( + + ); + }} +
@@ -1209,22 +1223,25 @@ export default function EmployeeManagementPage() { {/* Sub-tabs */}
- {(["profile", "activity", "access"] as const).map((tab, i) => { - const labels = ["Profile", "Activity Logs", "Access History"]; - const active = () => detailTab() === tab; - return ( - - ); - })} + + {(tab, getI) => { + const labels = ["Profile", "Activity Logs", "Access History"]; + const i = getI(); + const active = () => detailTab() === tab; + return ( + + ); + }} +
@@ -1235,17 +1252,21 @@ export default function EmployeeManagementPage() { Personal Information
- {[ - { l: "Full Name", v: viewingEmp()!.name }, - { l: "Email", v: viewingEmp()!.email }, - { l: "Phone", v: viewingEmp()!.phone || "—" }, - { l: "Gender", v: viewingEmp()!.gender || "—" }, - ].map((item) => ( -
-

{item.l}

-

{item.v}

-
- ))} + + {(item) => ( +
+

{item.l}

+

{item.v}

+
+ )} +
@@ -1253,17 +1274,21 @@ export default function EmployeeManagementPage() { Work Details
- {[ - { l: "Department", v: viewingEmp()!.department || "—" }, - { l: "Designation", v: viewingEmp()!.designation || "—" }, - { l: "Internal Role", v: viewingEmp()!.internalRole || "—" }, - { l: "Employment Type", v: viewingEmp()!.employmentType || "—" }, - ].map((item) => ( -
-

{item.l}

-

{item.v}

-
- ))} + + {(item) => ( +
+

{item.l}

+

{item.v}

+
+ )} +
diff --git a/src/routes/admin/external-dashboard-management/index.tsx b/src/routes/admin/external-dashboard-management/index.tsx index 8ba5ef5..d54c019 100644 --- a/src/routes/admin/external-dashboard-management/index.tsx +++ b/src/routes/admin/external-dashboard-management/index.tsx @@ -278,7 +278,7 @@ function rolePreviewPath(roleKey: string): string { const key = String(roleKey || "").toUpperCase(); if (key.includes("COMPANY")) return "/employers/dashboard"; if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER")) - return "/users/customer/dashboard"; + {return "/users/customer/dashboard";} if (key.includes("JOB_SEEKER") || key.includes("JOBSEEKER")) return "/users/candidate/dashboard"; if (key.includes("PHOTOGRAPHER")) return "/users/photographer/dashboard"; if (key.includes("MAKEUP")) return "/users/makeup/dashboard"; @@ -286,7 +286,7 @@ function rolePreviewPath(roleKey: string): string { if (key.includes("DEVELOPER")) return "/users/developers/dashboard"; if (key.includes("VIDEO")) return "/users/video-editors/dashboard"; if (key.includes("UGC") || (key.includes("CONTENT") && key.includes("CREATOR"))) - return "/users/ugc-content-creators/dashboard"; + {return "/users/ugc-content-creators/dashboard";} if (key.includes("FITNESS")) return "/users/fitness-trainers/dashboard"; if (key.includes("GRAPHIC")) return "/users/graphic-designers/dashboard"; if (key.includes("SOCIAL")) return "/users/social-media-managers/dashboard"; @@ -432,7 +432,7 @@ export default function ExternalDashboardManagementPage() { const key = role.key.toUpperCase(); if (key.includes("COMPANY")) map[role.id] = "COMPANY"; else if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER")) - map[role.id] = "CUSTOMER"; + {map[role.id] = "CUSTOMER";} else if (key.includes("JOB_SEEKER") || key.includes("JOBSEEKER")) map[role.id] = "JOB_SEEKER"; else map[role.id] = "PROFESSIONAL"; } @@ -590,9 +590,7 @@ export default function ExternalDashboardManagementPage() { setRoles( roleRows - .filter((r: any) => { - return r?.status === "ACTIVE" || r?.status === "INACTIVE"; - }) + .filter((r: any) => r?.status === "ACTIVE" || r?.status === "INACTIVE") .map((r: any) => ({ id: String(r?.id || ""), key: String(r?.code || r?.key || "").toUpperCase(), @@ -873,8 +871,8 @@ export default function ExternalDashboardManagementPage() {
- {(["general", "tabs", "sidebar", "fields", "theme", "preview", "full_preview"] as const).map( - (tab) => ( + + {(tab) => ( - ) - )} + )} +
@@ -1389,25 +1387,29 @@ export default function ExternalDashboardManagementPage() {
- {( - [ - ["name_asc", "Name (A-Z)"], - ["name_desc", "Name (Z-A)"], - ["updated_desc", "Updated (Newest)"], - ["updated_asc", "Updated (Oldest)"], - ] as const - ).map(([key, label]) => ( - - ))} + + {([key, label]) => ( + + )} +
@@ -1434,24 +1436,28 @@ export default function ExternalDashboardManagementPage() {
- {( - [ - ["all", "All Status"], - ["active", "Active"], - ["inactive", "Inactive"], - ] as const - ).map(([key, label]) => ( - - ))} + + {([key, label]) => ( + + )} +
@@ -1479,11 +1485,13 @@ export default function ExternalDashboardManagementPage() {
{h}
- {["Name", "Code", "Role", "Widgets", "Status", "Updated", "Actions"].map((h) => ( - - ))} + + {(h) => ( + + )} + diff --git a/src/routes/admin/external-roles.tsx b/src/routes/admin/external-roles.tsx index 7f4ed8d..ed5e25f 100644 --- a/src/routes/admin/external-roles.tsx +++ b/src/routes/admin/external-roles.tsx @@ -220,18 +220,14 @@ export default function ExternalRoleManagementPage() { } }; - const getPermission = (moduleKey: string): RolePermission | undefined => { - return rolePermissions().find((p) => p.module_key === moduleKey); - }; + const getPermission = (moduleKey: string): RolePermission | undefined => rolePermissions().find((p) => p.module_key === moduleKey); const hasAnyPermission = (moduleKey: string) => { const p = getPermission(moduleKey); return p && (p.can_view || p.can_list || p.can_create || p.can_update || p.can_delete); }; - const permissionKeyFor = (moduleKey: string, action: string) => { - return `${moduleKey}_${action.toLowerCase()}`; - }; + const permissionKeyFor = (moduleKey: string, action: string) => `${moduleKey}_${action.toLowerCase()}`; const isAllSelectedForAction = (action: PermissionAction) => { const actionKey = action.toLowerCase(); @@ -439,11 +435,13 @@ export default function ExternalRoleManagementPage() {
- {h} - + {h} +
- {["Role Name", "Key", "Persona Type", "Users", "Status", "Actions"].map((h) => ( - - ))} + + {(h) => ( + + )} + @@ -535,22 +533,25 @@ export default function ExternalRoleManagementPage() {
- {(["general", "permissions", "settings"] as const).map((tab, i) => { - const labels = ["General Information", "Module Access", "Role Settings"]; - const active = () => formTab() === tab; - return ( - - ); - })} + + {(tab, getI) => { + const labels = ["General Information", "Module Access", "Role Settings"]; + const i = getI(); + const active = () => formTab() === tab; + return ( + + ); + }} +
diff --git a/src/routes/admin/financial/adjust-credit.tsx b/src/routes/admin/financial/adjust-credit.tsx deleted file mode 100644 index 3c43569..0000000 --- a/src/routes/admin/financial/adjust-credit.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { onMount } from 'solid-js'; -import { useNavigate } from '@solidjs/router'; - -export default function AdjustCreditAliasPage() { - const navigate = useNavigate(); - onMount(() => navigate('/admin/credit', { replace: true })); - return

Redirecting to credit management...

; -} diff --git a/src/routes/admin/financial/reconcile.tsx b/src/routes/admin/financial/reconcile.tsx deleted file mode 100644 index 994e153..0000000 --- a/src/routes/admin/financial/reconcile.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { onMount } from 'solid-js'; -import { useNavigate } from '@solidjs/router'; - -export default function ReconcileAliasPage() { - const navigate = useNavigate(); - onMount(() => navigate('/admin/ledger', { replace: true })); - return

Redirecting to ledger management...

; -} diff --git a/src/routes/admin/help/support-bridge.tsx b/src/routes/admin/help/support-bridge.tsx deleted file mode 100644 index bd2ac54..0000000 --- a/src/routes/admin/help/support-bridge.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { A } from '@solidjs/router'; - -export default function HelpSupportBridgePage() { - return ( -
-
-

Support Bridge

-

This legacy help bridge now routes through the unified Support Management module.

-
-
-
-

Use the Support Management module to handle all support tickets and help requests.

- Open Support Management -
-
-
- ); -} diff --git a/src/routes/admin/index.tsx b/src/routes/admin/index.tsx index 1eefefc..47dc51a 100644 --- a/src/routes/admin/index.tsx +++ b/src/routes/admin/index.tsx @@ -271,22 +271,25 @@ export default function AdminHomePage() { kpi_credits_purchased: "credits", }; if (metrics.loading) return { state: "pending", statusLabel: "Loading..." }; + // Guard against error state — accessing metrics() when errored throws. + if (metrics.error) return { state: "empty", statusLabel: "No Data" }; const m = metrics()?.kpis?.find((k: any) => k.id === idMap[key]); if (m) return { state: "live", statusLabel: "Live Data", data: m }; return { state: "empty", statusLabel: "No Data" }; } if (metrics.loading) return { state: "pending", statusLabel: "Loading..." }; + if (metrics.error) return { state: "empty", statusLabel: "No Data" }; const m = metrics(); if (key === "chart_leads_trend") { const data = m?.trend_series; if (data && data.length > 0) - return { state: "live", statusLabel: "Live Data", data: { trend_series: data } }; + {return { state: "live", statusLabel: "Live Data", data: { trend_series: data } };} return { state: "empty", statusLabel: "No Data" }; } if (key === "chart_revenue_overview") { const data = m?.rev_series; if (data && data.length > 0) - return { state: "live", statusLabel: "Live Data", data: { rev_series: data } }; + {return { state: "live", statusLabel: "Live Data", data: { rev_series: data } };} return { state: "empty", statusLabel: "No Data" }; } const meta = WIDGET_META[key]; @@ -611,8 +614,8 @@ export default function AdminHomePage() {
- {["Edit Widget", "Duplicate Widget", "Hide Widget", "Remove Widget"].map( - (item) => ( + + {(item) => ( - ) - )} + )} +
diff --git a/src/routes/admin/internal-dashboard-management/index.tsx b/src/routes/admin/internal-dashboard-management/index.tsx index 2f7d72a..90c2a2d 100644 --- a/src/routes/admin/internal-dashboard-management/index.tsx +++ b/src/routes/admin/internal-dashboard-management/index.tsx @@ -257,12 +257,12 @@ export default function InternalDashboardManagementPage() {
- {(['general', 'tabs', 'sidebar', 'fields', 'preview'] as const).map((tab) => ( + {(tab) => ( - ))} + )}
@@ -353,14 +353,14 @@ export default function InternalDashboardManagementPage() {
- {([ + ( + ] as const}>{([key, label]) => ( - ))} + )}
@@ -371,13 +371,13 @@ export default function InternalDashboardManagementPage() {
- {([ + ( + ] as const}>{([key, label]) => ( - ))} + )}
@@ -391,9 +391,9 @@ export default function InternalDashboardManagementPage() {
- {h} - + {h} +
- {['Name', 'Code', 'Role', 'Widgets', 'Status', 'Updated', 'Actions'].map((h) => ( + {(h) => ( - ))} + )} diff --git a/src/routes/admin/jobs/index.tsx b/src/routes/admin/jobs/index.tsx index 71e72d7..a1b72ca 100644 --- a/src/routes/admin/jobs/index.tsx +++ b/src/routes/admin/jobs/index.tsx @@ -140,11 +140,11 @@ export default function JobsManagementPage() {
- {([ + setListTab('all') }, { key: 'active', label: 'Active', action: () => setListTab('active') }, { key: 'pending', label: 'Pending Approval', action: () => setListTab('pending') }, - ] as const).map((tab) => ( + ] as const}>{(tab) => ( - ))} + )}
@@ -173,16 +173,16 @@ export default function JobsManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -196,17 +196,17 @@ export default function JobsManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -223,9 +223,9 @@ export default function JobsManagementPage() {
{h}
- {['Job Title', 'Company', 'Rate', 'Location', 'Status', 'Actions'].map(h => ( + {h => ( - ))} + )} diff --git a/src/routes/admin/leads/index.tsx b/src/routes/admin/leads/index.tsx index e21a65a..7593388 100644 --- a/src/routes/admin/leads/index.tsx +++ b/src/routes/admin/leads/index.tsx @@ -109,16 +109,16 @@ export default function LeadsPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -133,16 +133,16 @@ export default function LeadsPage() {

Status

- {([ + ( + ] as const}>{(item) => ( - ))} + )}

Role

diff --git a/src/routes/admin/pricing.tsx b/src/routes/admin/pricing.tsx index c67b401..ef545b1 100644 --- a/src/routes/admin/pricing.tsx +++ b/src/routes/admin/pricing.tsx @@ -289,12 +289,12 @@ export default function PricingPage() { let r = packages() ?? []; const q = search().toLowerCase(); if (q) - r = r.filter( + {r = r.filter( (p) => p.name.toLowerCase().includes(q) || p.package_type.toLowerCase().includes(q) || (p.applicable_roles ?? []).some((rl) => rl.toLowerCase().includes(q)), - ); + );} if (typeFilter() !== 'all') r = r.filter((p) => p.package_type === typeFilter()); if (statusFilter() === 'active') r = r.filter((p) => p.is_active); if (statusFilter() === 'inactive') r = r.filter((p) => !p.is_active); @@ -428,9 +428,7 @@ export default function PricingPage() { }); }; - const getTypeLabel = (type: string) => { - return PACKAGE_TYPES.find((t) => t.value === type)?.label || type; - }; + const getTypeLabel = (type: string) => PACKAGE_TYPES.find((t) => t.value === type)?.label || type; return (
@@ -448,7 +446,7 @@ export default function PricingPage() {
- {(["packages", "create", "ai_packages"] as const).map((t) => ( + {(t) => ( - ))} + )}
diff --git a/src/routes/admin/role-ui-configs/index.tsx b/src/routes/admin/role-ui-configs/index.tsx index 244d92d..0f29f61 100644 --- a/src/routes/admin/role-ui-configs/index.tsx +++ b/src/routes/admin/role-ui-configs/index.tsx @@ -1,5 +1,5 @@ import { A, useNavigate, useSearchParams } from '@solidjs/router'; -import { createMemo, createResource, Show } from 'solid-js'; +import { For, createMemo, createResource, Show } from 'solid-js'; import ExternalRoleTabs from '~/components/admin/ExternalRoleTabs'; const API = ''; @@ -104,7 +104,7 @@ export default function RoleUiConfigsViewPage() {
- {(rows() || []).map((item) => { + {(item) => { const isActive = roleKey().toLowerCase() === item.roleKey.toLowerCase(); return ( ); - })} + }}
@@ -169,7 +169,7 @@ export default function RoleUiConfigsViewPage() {

0} fallback={'None'}> - {approvalFlags().map((flag) => {flag})} + {(flag) => {flag}}

@@ -181,7 +181,7 @@ export default function RoleUiConfigsViewPage() {

Enabled Modules

0} fallback={

No modules configured.

}>
- {selected()!.enabledModules.map((moduleKey) => {moduleKey})} + {(moduleKey) => {moduleKey}}
@@ -193,20 +193,20 @@ export default function RoleUiConfigsViewPage() {
- {permissionActions.map((action) => )} + {(action) => } - {selected()!.enabledModules.map((moduleKey) => ( + {(moduleKey) => ( - {permissionActions.map((action) => ( + {(action) => ( - ))} + )} - ))} + )}
{h}
Module{action}{action}
{moduleKey}
diff --git a/src/routes/admin/roles/[id]/edit.tsx b/src/routes/admin/roles/[id]/edit.tsx index 9eec3a3..1f8036c 100644 --- a/src/routes/admin/roles/[id]/edit.tsx +++ b/src/routes/admin/roles/[id]/edit.tsx @@ -245,13 +245,11 @@ export default function EditInternalRolePage() { {/* Inner sub-tabs */}
- {( - [ - { key: 'general', label: 'General Information' }, - { key: 'module', label: 'Module Access' }, - { key: 'settings', label: 'Role Settings' }, - ] as const - ).map((t) => ( + {(t) => ( - ))} + )}
{/* Error banner */} diff --git a/src/routes/admin/roles/create.tsx b/src/routes/admin/roles/create.tsx index cf1c3a9..d6b3eba 100644 --- a/src/routes/admin/roles/create.tsx +++ b/src/routes/admin/roles/create.tsx @@ -270,26 +270,26 @@ export default function CreateInternalRolePage() {
{/* Sub-tabs */}
- {( - [ - { key: "general", label: "General Information" }, - { key: "module", label: "Module Access" }, - { key: "settings", label: "Role Settings" }, - ] as const - ).map((t) => ( - - ))} + + {(t) => ( + + )} +
{/* Error banner */} @@ -412,24 +412,26 @@ export default function CreateInternalRolePage() { {module} - {ACTIONS.map((action) => { - const p = () => byAction()[action]; - return ( - - —} - > - toggleKey(p()!.key)} - class="h-4 w-4 accent-[#FF5E13] cursor-pointer" - /> - - - ); - })} + + {(action) => { + const p = () => byAction()[action]; + return ( + + —} + > + toggleKey(p()!.key)} + class="h-4 w-4 accent-[#FF5E13] cursor-pointer" + /> + + + ); + }} + { if (sortBy() === "name_desc") return b.name.localeCompare(a.name); if (sortBy() === "users_desc") - return Number(b.usersAssigned || 0) - Number(a.usersAssigned || 0); + {return Number(b.usersAssigned || 0) - Number(a.usersAssigned || 0);} if (sortBy() === "users_asc") - return Number(a.usersAssigned || 0) - Number(b.usersAssigned || 0); + {return Number(a.usersAssigned || 0) - Number(b.usersAssigned || 0);} return a.name.localeCompare(b.name); }); return sorted; @@ -585,35 +585,35 @@ export default function RoleManagementPage() { {/* ── LIST VIEW ── */}
- {( - [ - { - key: "all", - label: "All Roles", - action: () => { - setListTab("all"); - void load(); - }, + { + setListTab("all"); + void load(); }, - { - key: "create", - label: "Create Role", - action: () => { - setListTab("create"); - openCreate(); - }, + }, + { + key: "create", + label: "Create Role", + action: () => { + setListTab("create"); + openCreate(); }, - { key: "view", label: "View Role", action: () => setListTab("view") }, - ] as const - ).map((tab) => ( - - ))} + }, + { key: "view", label: "View Role", action: () => setListTab("view") }, + ] as const}> + {(tab) => ( + + )} +
@@ -659,25 +659,25 @@ export default function RoleManagementPage() {
- {( - [ - ["name_asc", "Name (A-Z)"], - ["name_desc", "Name (Z-A)"], - ["users_desc", "Users (High-Low)"], - ["users_asc", "Users (Low-High)"], - ] as const - ).map(([key, label]) => ( - - ))} + + {([key, label]) => ( + + )} +
@@ -704,25 +704,25 @@ export default function RoleManagementPage() {
- {( - [ - ["all", "All Status"], - ["ACTIVE", "Active"], - ["INACTIVE", "Inactive"], - ] as const - ).map(([key, label]) => ( - - ))} + + {([key, label]) => ( + + )} +
@@ -751,7 +751,7 @@ export default function RoleManagementPage() { - {[ + ( - - ))} + ]}> + {(h) => ( + + )} + @@ -947,22 +949,25 @@ export default function RoleManagementPage() {
- {(["general", "permissions", "settings"] as const).map((tab, i) => { - const labels = ["General Information", "Module Access", "Role Settings"]; - const active = () => formTab() === tab; - return ( - - ); - })} + + {(tab, getI) => { + const i = getI(); + const labels = ["General Information", "Module Access", "Role Settings"]; + const active = () => formTab() === tab; + return ( + + ); + }} +
@@ -1017,15 +1022,17 @@ export default function RoleManagementPage() {
@@ -1206,22 +1213,25 @@ export default function RoleManagementPage() {
- {(["permissions", "users", "logs"] as const).map((tab, i) => { - const labels = ["Permissions", "Assigned Users", "Activity Logs"]; - const active = () => detailTab() === tab; - return ( - - ); - })} + + {(tab, getI) => { + const i = getI(); + const labels = ["Permissions", "Assigned Users", "Activity Logs"]; + const active = () => detailTab() === tab; + return ( + + ); + }} +
diff --git a/src/routes/admin/runtime-roles/index.tsx b/src/routes/admin/runtime-roles/index.tsx index 37f5a0c..47cb4c6 100644 --- a/src/routes/admin/runtime-roles/index.tsx +++ b/src/routes/admin/runtime-roles/index.tsx @@ -128,24 +128,26 @@ export default function ExternalRolesPage() { {/* Stat cards */}
- {([ + stats().total, Icon: Globe, bg: 'bg-[#FFF1EB]', color: 'text-[#FF5E13]' }, { label: 'Active Roles', value: () => stats().active, Icon: ShieldCheck, bg: 'bg-[#ECFDF5]', color: 'text-[#059669]' }, { label: 'Inactive Roles', value: () => stats().inactive, Icon: ShieldOff, bg: 'bg-[#FEF2F2]', color: 'text-[#DC2626]' }, { label: 'Total Modules', value: () => roles().reduce((a, r) => a + r.enabledModules.length, 0), Icon: Layers, bg: 'bg-[#EFF6FF]', color: 'text-[#2563EB]' }, - ] as const).map(s => ( -
-
-
-

{s.label}

-

{s.value()}

-
-
- + ]}> + {(s) => ( +
+
+
+

{s.label}

+

{s.value()}

+
+
+ +
-
- ))} + )} +
{/* Table card */} diff --git a/src/routes/admin/support.tsx b/src/routes/admin/support.tsx index 6c14018..8772cf5 100644 --- a/src/routes/admin/support.tsx +++ b/src/routes/admin/support.tsx @@ -182,9 +182,9 @@ export default function SupportPage() { const sorted = [...all]; sorted.sort((a, b) => { if (sortBy() === "oldest") - return new Date(a.createdAt || 0).getTime() - new Date(b.createdAt || 0).getTime(); + {return new Date(a.createdAt || 0).getTime() - new Date(b.createdAt || 0).getTime();} if (sortBy() === "priority") - return (priorityRank[b.priority] || 0) - (priorityRank[a.priority] || 0); + {return (priorityRank[b.priority] || 0) - (priorityRank[a.priority] || 0);} return new Date(b.createdAt || 0).getTime() - new Date(a.createdAt || 0).getTime(); }); return sorted; diff --git a/src/routes/admin/tax.tsx b/src/routes/admin/tax.tsx index 18c464a..429dd4a 100644 --- a/src/routes/admin/tax.tsx +++ b/src/routes/admin/tax.tsx @@ -307,29 +307,31 @@ export default function TaxPage() {
0}> - {filteredTaxes().map((item) => ( - - - - - - - - ))} + + {(item) => ( + + + + + + + + )} +
- {h} - + {h} +
No records found.
{item.name}{item.rate}%{item.description || '—'} - - {item.is_active !== false ? 'Active' : 'Inactive'} - - -
- -
-
{item.name}{item.rate}%{item.description || '—'} + + {item.is_active !== false ? 'Active' : 'Inactive'} + + +
+ +
+
diff --git a/src/routes/admin/users/[id]/edit.tsx b/src/routes/admin/users/[id]/edit.tsx index 6d6c723..f9dcaef 100644 --- a/src/routes/admin/users/[id]/edit.tsx +++ b/src/routes/admin/users/[id]/edit.tsx @@ -1,5 +1,5 @@ import { A, useNavigate, useParams } from "@solidjs/router"; -import { createMemo, createResource, createSignal, Show } from "solid-js"; +import { createMemo, createResource, createSignal, For, Show } from "solid-js"; const API = ""; @@ -188,9 +188,9 @@ export default function EditUserPage() { > - {roles()?.map((r) => ( - - ))} + + {(r) => } + diff --git a/src/routes/admin/users/index.tsx b/src/routes/admin/users/index.tsx index 8c0dd65..0239885 100644 --- a/src/routes/admin/users/index.tsx +++ b/src/routes/admin/users/index.tsx @@ -193,20 +193,20 @@ export default function UsersManagementPage() { if (listTab() === "no_role") list = list.filter((u) => u.registeredRoles.length === 0); if (listTab() === "registered") list = list.filter((u) => u.registeredRoles.length > 0); if (listTab() === "pending") - list = list.filter( + {list = list.filter( (u) => u.registeredRoles.some((r) => r.status === "PENDING") || u.verificationStatus === "PENDING" || u.verificationStatus === "IN_REVIEW" - ); + );} if (listTab() === "approved") list = list.filter((u) => u.verificationStatus === "VERIFIED"); if (listTab() === "suspended") list = list.filter((u) => u.accountStatus === "SUSPENDED"); if (statusFilter() === "active") list = list.filter((u) => u.accountStatus === "ACTIVE"); if (statusFilter() === "pending") - list = list.filter( + {list = list.filter( (u) => u.verificationStatus === "PENDING" || u.verificationStatus === "IN_REVIEW" - ); + );} if (statusFilter() === "suspended") list = list.filter((u) => u.accountStatus === "SUSPENDED"); if (statusFilter() === "blocked") list = list.filter((u) => u.accountStatus === "BLOCKED"); @@ -290,7 +290,7 @@ export default function UsersManagementPage() { prev.map((r) => (r.id === user.id ? { ...r, accountStatus: nextStatus as any } : r)) ); if (selectedUser()?.id === user.id) - setSelectedUser({ ...user, accountStatus: nextStatus as any }); + {setSelectedUser({ ...user, accountStatus: nextStatus as any });} try { const r = await fetch(`/api/admin/users/${user.id}/status`, { @@ -310,7 +310,7 @@ export default function UsersManagementPage() { prev.map((r) => (r.id === user.id ? { ...r, accountStatus: previousStatus } : r)) ); if (selectedUser()?.id === user.id) - setSelectedUser({ ...user, accountStatus: previousStatus }); + {setSelectedUser({ ...user, accountStatus: previousStatus });} setActionError(`Failed to update status for ${user.name}. Please try again.`); } }; @@ -346,14 +346,14 @@ export default function UsersManagementPage() {
- {[ + ( + ]}>{(card) => (

{card.label} @@ -364,13 +364,12 @@ export default function UsersManagementPage() { {card.value}

- ))} + )}
- {( - [ + ( + ] as const}>{(tab) => ( - ))} + )}
@@ -509,8 +507,7 @@ export default function UsersManagementPage() {
- {( - [ + ( + ] as const}>{(tab) => ( - ))} + )}
@@ -721,14 +717,12 @@ export default function UsersManagementPage() {
- {( - [ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -770,15 +764,13 @@ export default function UsersManagementPage() {

Status

- {( - [ + ( + ] as const}>{(item) => ( - ))} + )}

Role Group

- {( - [ + ( + ] as const}>{(item) => ( - ))} + )}
diff --git a/src/routes/admin/verification-status/index.tsx b/src/routes/admin/verification-status/index.tsx deleted file mode 100644 index ae21af1..0000000 --- a/src/routes/admin/verification-status/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { useNavigate } from '@solidjs/router'; -import { onMount } from 'solid-js'; - -export default function VerificationStatusPage() { - const navigate = useNavigate(); - onMount(() => navigate('/admin/verification', { replace: true })); - return null; -} diff --git a/src/routes/admin/verification/[id].tsx b/src/routes/admin/verification/[id].tsx index a7b0c5d..6fe5b5c 100644 --- a/src/routes/admin/verification/[id].tsx +++ b/src/routes/admin/verification/[id].tsx @@ -391,14 +391,14 @@ export default function VerificationReviewDetailPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -535,7 +535,7 @@ export default function VerificationReviewDetailPage() {
- {['Document', 'File', 'Status'].map((h) => )} + {(h) => } 0} fallback={}> {(doc) => ( diff --git a/src/routes/admin/verification/index.tsx b/src/routes/admin/verification/index.tsx index 0294dc5..b39394f 100644 --- a/src/routes/admin/verification/index.tsx +++ b/src/routes/admin/verification/index.tsx @@ -644,10 +644,10 @@ export default function VerificationManagementPage() {
- {([ + ( + ] as const}>{(tab) => ( - ))} + )}
- {([ + ( + ] as const}>{(tab) => ( - ))} + )}
@@ -702,11 +702,11 @@ export default function VerificationManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -730,7 +730,7 @@ export default function VerificationManagementPage() {
- {([ + ( + ] as const}>{(item) => ( - ))} + )}
@@ -765,9 +765,9 @@ export default function VerificationManagementPage() {
{h}
{h}
No documents uploaded yet.
- {['Submission ID', 'Type', 'Applicant Name', 'Role', 'Submitted On', 'Status', 'Priority', 'Actions'].map((header) => ( + {(header) => ( - ))} + )} @@ -933,9 +933,9 @@ export default function VerificationManagementPage() {
{header}
- {['Document', 'State', 'View', 'Request'].map((header) => ( + {(header) => ( - ))} + )} diff --git a/src/routes/admin/workspace/[menuId].tsx b/src/routes/admin/workspace/[menuId].tsx deleted file mode 100644 index 14c26c5..0000000 --- a/src/routes/admin/workspace/[menuId].tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { onMount } from 'solid-js'; -import { useNavigate, useParams } from '@solidjs/router'; - -export default function WorkspaceMenuAliasPage() { - const navigate = useNavigate(); - const params = useParams(); - onMount(() => navigate('/admin', { replace: true })); - return ( -
-

Redirecting workspace menu {params.menuId} to dashboard...

-
- ); -} diff --git a/src/routes/login.tsx b/src/routes/login.tsx index 5662f74..1f54067 100644 --- a/src/routes/login.tsx +++ b/src/routes/login.tsx @@ -41,12 +41,14 @@ export default function LoginPage() { // same server-side captcha challenge the public site uses — generated by // the users service at /api/auth/captcha and verified against shared Redis. // Routed through /api/gateway/* (this app's generic gateway proxy) rather - // than a bare /api/auth/* path — there is no server route for that prefix, - // so it would otherwise silently fall through to the SPA's index.html. + // The admin is a plain Vite SPA — /api/* routes are proxied directly to the + // gateway (vite.config.ts proxy: /api → http://localhost:9100), so /api/auth/captcha + // reaches the users service correctly. The /api/gateway prefix is only needed + // in the SolidStart frontend where the middleware otherwise falls through to Nitro. const loadCaptcha = async () => { setCaptchaInput(''); try { - const r = await fetch('/api/gateway/auth/captcha', { method: 'POST', headers: { Accept: 'application/json' }, credentials: 'include' }); + const r = await fetch('/api/auth/captcha', { method: 'POST', headers: { Accept: 'application/json' }, credentials: 'include' }); const payload = await r.json().catch(() => ({})); setCaptchaId(String(payload?.captcha_id || '')); setCaptchaChallenge(String(payload?.challenge || '')); diff --git a/src/stories/admin/AdminPages.stories.tsx b/src/stories/admin/AdminPages.stories.tsx index edc9637..b33907e 100644 --- a/src/stories/admin/AdminPages.stories.tsx +++ b/src/stories/admin/AdminPages.stories.tsx @@ -5,8 +5,6 @@ import '../../app.css'; import AdminHomePage from '../../routes/admin/index'; import ApprovalPage from '../../routes/admin/approval'; import VerificationPage from '../../routes/admin/verification'; -import DepartmentManagementPage from '../../routes/admin/department-management'; -import DesignationManagementPage from '../../routes/admin/designation-management'; import EmployeesPage from '../../routes/admin/employees'; import InternalDashboardManagementPage from '../../routes/admin/internal-dashboard-management'; import ExternalDashboardManagementPage from '../../routes/admin/external-dashboard-management'; @@ -47,14 +45,6 @@ export const Approval: Story = { render: () => renderRoute('/admin/approval', ApprovalPage), }; -export const DepartmentManagement: Story = { - render: () => renderRoute('/admin/department-management', DepartmentManagementPage), -}; - -export const DesignationManagement: Story = { - render: () => renderRoute('/admin/designation-management', DesignationManagementPage), -}; - export const EmployeeManagement: Story = { render: () => renderRoute('/admin/employees', EmployeesPage), }; diff --git a/src/test/setup.ts b/src/test/setup.ts index 0a797bb..6066526 100644 --- a/src/test/setup.ts +++ b/src/test/setup.ts @@ -5,26 +5,18 @@ import { http, HttpResponse } from 'msw'; // Mock API responses globally for frontend tests const server = setupServer( - http.get('/api/admin/companies', () => { - return HttpResponse.json([ + http.get('/api/admin/companies', () => HttpResponse.json([ { id: '1', company_name: 'Test Co', status: 'ACTIVE' } - ]); - }), - http.get('/api/admin/users', () => { - return HttpResponse.json([ + ])), + http.get('/api/admin/users', () => HttpResponse.json([ { id: '1', full_name: 'Admin User', email: 'admin@example.com', status: 'ACTIVE' } - ]); - }), - http.get('/api/admin/jobs', () => { - return HttpResponse.json([ + ])), + http.get('/api/admin/jobs', () => HttpResponse.json([ { id: '1', title: 'Developer', status: 'OPEN' } - ]); - }), - http.get('/api/admin/leads', () => { - return HttpResponse.json([ + ])), + http.get('/api/admin/leads', () => HttpResponse.json([ { id: '1', title: 'Need a developer', status: 'PENDING' } - ]); - }) + ])) ); beforeAll(() => server.listen());
{header}