commit d2a577f254b3939ac4dc6684c805fa1d9fa3d5ee
Author: sajjadtalkhabi <97734061+sajjadtalkhabi@users.noreply.github.com>
Date: Wed May 13 01:43:05 2026 +0330
first commit
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..86a63dc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.env b/.env
new file mode 100644
index 0000000..2be7680
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+VITE_API_BASE_URL=
+VITE_USE_MOCKS=true
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..1be587a
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,95 @@
+module.exports = {
+ root: true,
+ env: {
+ browser: true,
+ node: true,
+ es2021: true,
+ },
+ plugins: ['prettier', 'unicorn', 'import'],
+ ignorePatterns: ['node_modules/', 'dist/', 'build/', '*.min.js'],
+ parserOptions: {
+ ecmaVersion: 2021,
+ sourceType: 'module',
+ },
+ extends: [
+ 'plugin:unicorn/recommended',
+ 'eslint:recommended',
+ 'plugin:prettier/recommended',
+ 'eslint-config-prettier',
+ 'plugin:vue/vue3-essential',
+ ],
+ overrides: [
+ {
+ files: ['**/*.vue'],
+ parser: 'vue-eslint-parser',
+ parserOptions: {
+ ecmaVersion: 2021,
+ sourceType: 'module',
+ },
+ },
+ {
+ files: ['**/*.cjs'],
+ parserOptions: {
+ sourceType: 'script',
+ },
+ },
+ ],
+ rules: {
+ 'no-alert': 'error',
+ 'no-shadow': 'off',
+ 'no-console': 'off',
+ 'import/order': 'off',
+ 'dot-notation': 'error',
+ 'no-else-return': 'off',
+ 'unicorn/no-null': 'off',
+ semi: ['error', 'never'],
+ 'import/namespace': 'off',
+ 'no-implied-eval': 'error',
+ 'no-return-await': 'error',
+ 'no-nested-ternary': 'off',
+ 'no-param-reassign': 'off',
+ 'no-throw-literal': 'error',
+ 'consistent-return': 'off',
+ 'no-useless-catch': 'off',
+ 'prefer-destructuring': 'off',
+ 'import/no-unresolved': 'off',
+ 'no-underscore-dangle': 'off',
+ 'unicorn/prefer-spread': 'off',
+ 'unicorn/prefer-module': 'off',
+ 'unicorn/filename-case': 'off',
+ 'unicorn/no-array-reduce': 'off',
+ 'no-constant-condition': 'error',
+ 'unicorn/no-array-for-each': 'off',
+ 'unicorn/prefer-node-protocol': 'off',
+ 'import/prefer-default-export': 'off',
+ 'unicorn/prevent-abbreviations': 'off',
+ 'unicorn/prefer-string-replace-all': 'off',
+ 'unicorn/consistent-function-scoping': 'off',
+ 'unicorn/no-thenable': 'off',
+ 'unicorn/no-static-only-class': 'off',
+ 'unicorn/prefer-dom-node-text-content': 'off',
+ 'unicorn/prefer-logical-operator-over-ternary': 'off',
+ 'unicorn/prefer-number-properties': 'off',
+ 'unicorn/prefer-ternary': 'off',
+ 'no-unused-vars': 'off',
+ 'no-irregular-whitespace': 'off',
+ 'no-empty': 'off',
+ 'import/extensions': 'off',
+ 'vue/multi-word-component-names': 'off',
+ 'vue/component-name-in-template-casing': 'off',
+ 'vue/html-self-closing': 'off',
+ 'vue/max-attributes-per-line': 'off',
+ 'vue/html-indent': 'off',
+ 'vue/no-unused-components': 'off',
+ 'vue/no-reserved-component-names': 'off',
+ 'vue/no-unused-vars': 'off',
+ 'vue/require-v-for-key': 'off',
+ 'vue/require-toggle-inside-transition': 'off',
+ 'vue/require-valid-default-prop': 'off',
+ 'vue/no-deprecated-props-default-this': 'off',
+ 'vue/no-duplicate-attributes': 'off',
+ 'vue/no-side-effects-in-computed-properties': 'off',
+ 'vue/valid-v-on': 'off',
+ 'padding-line-between-statements': 'off',
+ },
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..58fa28a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+node_modules
+dist
+dist-ssr
+*.local
+.DS_Store
+.env.local
+.env.*.local
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..d24fdfc
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx lint-staged
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..4942c74
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,5 @@
+node_modules
+dist
+build
+*.min.js
+package-lock.json
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..fb560d1
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,14 @@
+{
+ "printWidth": 100,
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "arrowParens": "always",
+ "proseWrap": "never",
+ "htmlWhitespaceSensitivity": "ignore",
+ "endOfLine": "lf"
+}
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 0000000..8127d21
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,4 @@
+node_modules
+dist
+build
+*.min.css
diff --git a/.stylelintrc.json b/.stylelintrc.json
new file mode 100644
index 0000000..6d0174f
--- /dev/null
+++ b/.stylelintrc.json
@@ -0,0 +1,58 @@
+{
+ "extends": ["stylelint-config-standard-scss", "stylelint-config-html"],
+ "plugins": ["stylelint-declaration-block-no-ignored-properties"],
+ "rules": {
+ "media-feature-range-notation": "prefix",
+ "property-no-vendor-prefix": null,
+ "color-function-notation": "legacy",
+ "declaration-block-no-redundant-longhand-properties": [
+ true,
+ {
+ "ignoreShorthands": ["inset", "place-content"]
+ }
+ ],
+ "selector-pseudo-class-no-unknown": [
+ true,
+ {
+ "ignorePseudoClasses": ["global", "deep", "slotted"]
+ }
+ ],
+ "at-rule-no-unknown": null,
+ "scss/at-rule-no-unknown": [
+ true,
+ {
+ "ignoreAtRules": ["use", "forward"]
+ }
+ ],
+ "font-family-no-missing-generic-family-keyword": null,
+ "no-descending-specificity": null,
+ "plugin/declaration-block-no-ignored-properties": true,
+ "selector-class-pattern": [
+ "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?:__[a-z0-9]+(?:-[a-z0-9]+)*)?(?:--[a-z0-9]+(?:-[a-z0-9]+)*)?$",
+ {
+ "message": "Expected class selector to follow kebab-case BEM (block__element--modifier)"
+ }
+ ]
+ },
+ "overrides": [
+ {
+ "files": ["*.vue", "**/*.vue"],
+ "customSyntax": "postcss-html",
+ "rules": {
+ "selector-pseudo-element-no-unknown": [
+ true,
+ {
+ "ignorePseudoElements": ["v-deep", "v-global", "v-slotted", "deep"]
+ }
+ ],
+ "selector-pseudo-class-no-unknown": [
+ true,
+ {
+ "ignorePseudoClasses": ["deep", "global", "slotted"]
+ }
+ ]
+ }
+ }
+ ],
+ "ignoreFiles": ["**/*.js", "**/*.ts", "node_modules/**", "dist/**", "build/**"]
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..0c017a1
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,11 @@
+
+{
+ "recommendations": [
+ "esbenp.prettier-vscode",
+ "dbaeumer.vscode-eslint",
+ "editorconfig.editorconfig",
+ "stylelint.vscode-stylelint",
+ "streetsidesoftware.code-spell-checker",
+ "streetsidesoftware.code-spell-checker-persian"
+ ]
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..09d93c1
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Banu
+
+
+
+
+
+
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..686295e
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ },
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..258308a
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,7850 @@
+{
+ "name": "banu-front",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "banu-front",
+ "version": "0.0.0",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.6",
+ "@tanstack/vue-query": "^5.62.2",
+ "@tanstack/vue-query-devtools": "^5.62.2",
+ "axios": "^1.12.2",
+ "lodash": "^4.18.1",
+ "pinia": "^3.0.3",
+ "vue": "^3.5.21",
+ "vue-advanced-cropper": "^2.8.9",
+ "vue-router": "^4.5.1",
+ "vue3-persian-datetime-picker": "^1.2.2",
+ "vue3-toastify": "^0.2.5",
+ "yup": "^1.7.0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^6.0.1",
+ "eslint": "^8.57.0",
+ "eslint-config-prettier": "^8.10.2",
+ "eslint-plugin-import": "^2.32.0",
+ "eslint-plugin-prettier": "^4.2.1",
+ "eslint-plugin-unicorn": "^55.0.0",
+ "eslint-plugin-vue": "^9.15.1",
+ "postcss-html": "^1.8.0",
+ "prettier": "2.8.8",
+ "sass": "^1.83.0",
+ "stylelint": "^16.0.0",
+ "stylelint-config-html": "^1.1.0",
+ "stylelint-config-standard-scss": "^12.0.0",
+ "stylelint-declaration-block-no-ignored-properties": "^2.8.0",
+ "vite": "^7.1.6",
+ "vite-svg-loader": "^5.1.0",
+ "vue-eslint-parser": "^10.2.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/code-frame/node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
+ "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@cacheable/memory": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.8.tgz",
+ "integrity": "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.4.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/memory/node_modules/keyv": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@keyv/serialize": "^1.1.1"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.1.tgz",
+ "integrity": "sha512-eiFgzCbIneyMlLOmNG4g9xzF7Hv3Mga4LjxjcSC/ues6VYq2+gUbQI8JqNuw/ZM8tJIeIaBGpswAsqV2V7ApgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils/node_modules/keyv": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@keyv/serialize": "^1.1.1"
+ }
+ },
+ "node_modules/@csstools/css-parser-algorithms": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
+ "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-syntax-patches-for-csstree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz",
+ "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "peerDependencies": {
+ "css-tree": "^3.2.1"
+ },
+ "peerDependenciesMeta": {
+ "css-tree": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@csstools/css-tokenizer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
+ "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@csstools/media-query-list-parser": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz",
+ "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@dual-bundle/import-meta-resolve": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz",
+ "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/JounQin"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
+ "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
+ "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
+ "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
+ "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
+ "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
+ "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
+ "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
+ "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
+ "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
+ "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
+ "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
+ "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
+ "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
+ "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
+ "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
+ "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
+ "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
+ "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
+ "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
+ "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
+ "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
+ "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
+ "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
+ "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "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/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/@floating-ui/core": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+ "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+ "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.5",
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+ "license": "MIT"
+ },
+ "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/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/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
+ "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.3",
+ "is-glob": "^4.0.3",
+ "node-addon-api": "^7.0.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.5.6",
+ "@parcel/watcher-darwin-arm64": "2.5.6",
+ "@parcel/watcher-darwin-x64": "2.5.6",
+ "@parcel/watcher-freebsd-x64": "2.5.6",
+ "@parcel/watcher-linux-arm-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm-musl": "2.5.6",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm64-musl": "2.5.6",
+ "@parcel/watcher-linux-x64-glibc": "2.5.6",
+ "@parcel/watcher-linux-x64-musl": "2.5.6",
+ "@parcel/watcher-win32-arm64": "2.5.6",
+ "@parcel/watcher-win32-ia32": "2.5.6",
+ "@parcel/watcher-win32-x64": "2.5.6"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
+ "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
+ "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
+ "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
+ "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
+ "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
+ "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
+ "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
+ "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
+ "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
+ "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
+ "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
+ "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
+ "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz",
+ "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz",
+ "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz",
+ "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz",
+ "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz",
+ "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz",
+ "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz",
+ "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz",
+ "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz",
+ "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz",
+ "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz",
+ "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz",
+ "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz",
+ "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz",
+ "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz",
+ "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz",
+ "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz",
+ "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz",
+ "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz",
+ "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz",
+ "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz",
+ "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz",
+ "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz",
+ "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz",
+ "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz",
+ "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz",
+ "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tanstack/match-sorter-utils": {
+ "version": "8.19.4",
+ "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz",
+ "integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==",
+ "license": "MIT",
+ "dependencies": {
+ "remove-accents": "0.5.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/query-core": {
+ "version": "5.100.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.9.tgz",
+ "integrity": "sha512-SJSFw1S8+kQ0+knv/XGfrbocWoAlT7vDKsSImtLx3ZPQmEcR46hkDjLSvynSy25N8Ms4tIEini1FuBd5k7IscQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/query-devtools": {
+ "version": "5.90.1",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.90.1.tgz",
+ "integrity": "sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/vue-query": {
+ "version": "5.100.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.100.9.tgz",
+ "integrity": "sha512-wGiv/AirRuITlTDl87zdBRaZIZTejMItUswKgMzzcX/1gfn95iKw2EaCuz7qlX9ceB0DwBj9FqaroLnDoJCecg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/match-sorter-utils": "^8.19.4",
+ "@tanstack/query-core": "5.100.9",
+ "@vue/devtools-api": "^6.6.3",
+ "vue-demi": "^0.14.10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.1.2",
+ "vue": "^2.6.0 || ^3.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@tanstack/vue-query-devtools": {
+ "version": "5.91.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/vue-query-devtools/-/vue-query-devtools-5.91.0.tgz",
+ "integrity": "sha512-Kn6p5ffEKUj+YGEP+BapoPI8kUiPtNnFDyzjTvUx6GHbyfzfefQPhYoRtFiWeyrGHjUB/Mvtnr7Rosbzs/ngVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/query-devtools": "5.90.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "@tanstack/vue-query": "^5.90.5",
+ "vue": "^3.3.0"
+ }
+ },
+ "node_modules/@tanstack/vue-query/node_modules/vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@types/esrecurse": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
+ "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz",
+ "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.6.tgz",
+ "integrity": "sha512-u9HHgfrq3AjXlysn0eINFnWQOJQLO9WN6VprZ8FXl7A2bYisv3Hui9Ij+7QZ41F/WYWarHjwBbXtD7dKg3uxbg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "1.0.0-rc.13"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+ "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.3",
+ "@vue/shared": "3.5.34",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-core/node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+ "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.34",
+ "@vue/shared": "3.5.34"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
+ "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.3",
+ "@vue/compiler-core": "3.5.34",
+ "@vue/compiler-dom": "3.5.34",
+ "@vue/compiler-ssr": "3.5.34",
+ "@vue/shared": "3.5.34",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.14",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+ "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.34",
+ "@vue/shared": "3.5.34"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "6.6.4",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+ "license": "MIT"
+ },
+ "node_modules/@vue/devtools-kit": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz",
+ "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-shared": "^7.7.9",
+ "birpc": "^2.3.0",
+ "hookable": "^5.5.3",
+ "mitt": "^3.0.1",
+ "perfect-debounce": "^1.0.0",
+ "speakingurl": "^14.0.1",
+ "superjson": "^2.2.2"
+ }
+ },
+ "node_modules/@vue/devtools-shared": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz",
+ "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==",
+ "license": "MIT",
+ "dependencies": {
+ "rfdc": "^1.4.1"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz",
+ "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.34"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz",
+ "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.34",
+ "@vue/shared": "3.5.34"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz",
+ "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.34",
+ "@vue/runtime-core": "3.5.34",
+ "@vue/shared": "3.5.34",
+ "csstype": "^3.2.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz",
+ "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.34",
+ "@vue/shared": "3.5.34"
+ },
+ "peerDependencies": {
+ "vue": "3.5.34"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz",
+ "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+ "license": "MIT"
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "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-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/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/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/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
+ "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.29",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz",
+ "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/birpc": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz",
+ "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
+ "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cacheable": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.5.tgz",
+ "integrity": "sha512-EQfaKe09tl615iNvq/TBRWTFf1AKJNXYQSsMx0Z3EI0nA+pVsVPS8wJhnRlkbdacKPh1d0qVIhwTc2zsQNFEEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.0.8",
+ "@cacheable/utils": "^2.4.1",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
+ },
+ "node_modules/cacheable/node_modules/keyv": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@keyv/serialize": "^1.1.1"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
+ "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "get-intrinsic": "^1.3.0",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/caniuse-lite": {
+ "version": "1.0.30001792",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz",
+ "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "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/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
+ "node_modules/clean-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz",
+ "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/clean-regexp/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "license": "MIT"
+ },
+ "node_modules/copy-anything": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz",
+ "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-what": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz",
+ "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz",
+ "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-functions-list": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz",
+ "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debounce": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "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/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/easy-bem": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz",
+ "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.353",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz",
+ "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz",
+ "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.7",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
+ "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.7",
+ "@esbuild/android-arm": "0.27.7",
+ "@esbuild/android-arm64": "0.27.7",
+ "@esbuild/android-x64": "0.27.7",
+ "@esbuild/darwin-arm64": "0.27.7",
+ "@esbuild/darwin-x64": "0.27.7",
+ "@esbuild/freebsd-arm64": "0.27.7",
+ "@esbuild/freebsd-x64": "0.27.7",
+ "@esbuild/linux-arm": "0.27.7",
+ "@esbuild/linux-arm64": "0.27.7",
+ "@esbuild/linux-ia32": "0.27.7",
+ "@esbuild/linux-loong64": "0.27.7",
+ "@esbuild/linux-mips64el": "0.27.7",
+ "@esbuild/linux-ppc64": "0.27.7",
+ "@esbuild/linux-riscv64": "0.27.7",
+ "@esbuild/linux-s390x": "0.27.7",
+ "@esbuild/linux-x64": "0.27.7",
+ "@esbuild/netbsd-arm64": "0.27.7",
+ "@esbuild/netbsd-x64": "0.27.7",
+ "@esbuild/openbsd-arm64": "0.27.7",
+ "@esbuild/openbsd-x64": "0.27.7",
+ "@esbuild/openharmony-arm64": "0.27.7",
+ "@esbuild/sunos-x64": "0.27.7",
+ "@esbuild/win32-arm64": "0.27.7",
+ "@esbuild/win32-ia32": "0.27.7",
+ "@esbuild/win32-x64": "0.27.7"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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": {
+ "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-config-prettier": {
+ "version": "8.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz",
+ "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
+ "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.16.1",
+ "resolve": "^2.0.0-next.6"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
+ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.5.tgz",
+ "integrity": "sha512-9Ni+xgemM2IWLq6aXEpP2+V/V30GeA/46Ar629vcMqVPodFFWC9skHu/D1phvuqtS8bJCFnNf01/qcmqYEwNfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.28.0",
+ "prettier": ">=2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-unicorn": {
+ "version": "55.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz",
+ "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.24.5",
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "ci-info": "^4.0.0",
+ "clean-regexp": "^1.0.0",
+ "core-js-compat": "^3.37.0",
+ "esquery": "^1.5.0",
+ "globals": "^15.7.0",
+ "indent-string": "^4.0.0",
+ "is-builtin-module": "^3.2.1",
+ "jsesc": "^3.0.2",
+ "pluralize": "^8.0.0",
+ "read-pkg-up": "^7.0.1",
+ "regexp-tree": "^0.1.27",
+ "regjsparser": "^0.10.0",
+ "semver": "^7.6.1",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1"
+ },
+ "peerDependencies": {
+ "eslint": ">=8.56.0"
+ }
+ },
+ "node_modules/eslint-plugin-unicorn/node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-plugin-unicorn/node_modules/semver": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
+ "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-vue": {
+ "version": "9.33.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz",
+ "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "globals": "^13.24.0",
+ "natural-compare": "^1.4.0",
+ "nth-check": "^2.1.1",
+ "postcss-selector-parser": "^6.0.15",
+ "semver": "^7.6.3",
+ "vue-eslint-parser": "^9.4.3",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/semver": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
+ "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/vue-eslint-parser": {
+ "version": "9.4.3",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
+ "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.1",
+ "esquery": "^1.4.0",
+ "lodash": "^4.17.21",
+ "semver": "^7.3.6"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
+ }
+ },
+ "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/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/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/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-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/fast-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
+ "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastest-levenshtein": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.9.1"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "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/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "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.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "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",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 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==",
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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",
+ "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/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/global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "global-prefix": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "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/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/globjoin": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+ "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+ "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+ "license": "MIT"
+ },
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "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/immutable": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
+ "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/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==",
+ "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.",
+ "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/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-builtin-module": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
+ "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "builtin-modules": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-what": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
+ "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jalaali-js": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.8.tgz",
+ "integrity": "sha512-Jl/EwY84JwjW2wsWqeU4pNd22VNQ7EkjI36bDuLw31wH98WQW4fPjD0+mG7cdCK+Y8D6s9R3zLiQ3LaKu6bD8A==",
+ "license": "MIT"
+ },
+ "node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "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-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "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": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "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/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/known-css-properties": {
+ "version": "0.37.0",
+ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz",
+ "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/mathml-tag-names": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/meow": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
+ "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/micromatch/node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "license": "MIT"
+ },
+ "node_modules/moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/moment-jalaali": {
+ "version": "0.9.6",
+ "resolved": "https://registry.npmjs.org/moment-jalaali/-/moment-jalaali-0.9.6.tgz",
+ "integrity": "sha512-v8wXjQplvk5ez+sUqgsWIrafwIf1BEXXvzTYwsg1wHcqh27nSgKPCJ6FnZRrCz03MoNyB9N31L0oms+vE8Rq7g==",
+ "license": "MIT",
+ "dependencies": {
+ "jalaali-js": "^1.1.0",
+ "moment": "^2.22.2",
+ "moment-timezone": "^0.5.21",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "node_modules/moment-timezone": {
+ "version": "0.5.48",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
+ "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
+ "license": "MIT",
+ "dependencies": {
+ "moment": "^2.29.4"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "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/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/node-exports-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
+ "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array.prototype.flatmap": "^1.3.3",
+ "es-errors": "^1.3.0",
+ "object.entries": "^1.1.9",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.38",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz",
+ "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "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",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "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/perfect-debounce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pinia": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz",
+ "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-api": "^7.7.7"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.5.0",
+ "vue": "^3.5.11"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pinia/node_modules/@vue/devtools-api": {
+ "version": "7.7.9",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz",
+ "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-kit": "^7.7.9"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
+ "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-html": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.8.1.tgz",
+ "integrity": "sha512-OLF6P7qctfAWayOhLpcVnTGqVeJzu2W3WpIYelfz2+JV5oGxfkcEvweN9U4XpeqE0P98dcD9ssusGwlF0TK0uQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "htmlparser2": "^8.0.0",
+ "js-tokens": "^9.0.0",
+ "postcss": "^8.5.0",
+ "postcss-safe-parser": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12 || >=14"
+ }
+ },
+ "node_modules/postcss-media-query-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+ "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/postcss-resolve-nested-selector": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz",
+ "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/postcss-safe-parser": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
+ "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3.3"
+ }
+ },
+ "node_modules/postcss-scss": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz",
+ "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss-scss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.29"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz",
+ "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp-tree": {
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
+ "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "regexp-tree": "bin/regexp-tree"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regjsparser": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz",
+ "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/remove-accents": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
+ "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==",
+ "license": "MIT"
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "2.0.0-next.6",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz",
+ "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "node-exports-info": "^1.6.0",
+ "object-keys": "^1.1.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "license": "MIT"
+ },
+ "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",
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.60.3",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz",
+ "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.60.3",
+ "@rollup/rollup-android-arm64": "4.60.3",
+ "@rollup/rollup-darwin-arm64": "4.60.3",
+ "@rollup/rollup-darwin-x64": "4.60.3",
+ "@rollup/rollup-freebsd-arm64": "4.60.3",
+ "@rollup/rollup-freebsd-x64": "4.60.3",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.60.3",
+ "@rollup/rollup-linux-arm-musleabihf": "4.60.3",
+ "@rollup/rollup-linux-arm64-gnu": "4.60.3",
+ "@rollup/rollup-linux-arm64-musl": "4.60.3",
+ "@rollup/rollup-linux-loong64-gnu": "4.60.3",
+ "@rollup/rollup-linux-loong64-musl": "4.60.3",
+ "@rollup/rollup-linux-ppc64-gnu": "4.60.3",
+ "@rollup/rollup-linux-ppc64-musl": "4.60.3",
+ "@rollup/rollup-linux-riscv64-gnu": "4.60.3",
+ "@rollup/rollup-linux-riscv64-musl": "4.60.3",
+ "@rollup/rollup-linux-s390x-gnu": "4.60.3",
+ "@rollup/rollup-linux-x64-gnu": "4.60.3",
+ "@rollup/rollup-linux-x64-musl": "4.60.3",
+ "@rollup/rollup-openbsd-x64": "4.60.3",
+ "@rollup/rollup-openharmony-arm64": "4.60.3",
+ "@rollup/rollup-win32-arm64-msvc": "4.60.3",
+ "@rollup/rollup-win32-ia32-msvc": "4.60.3",
+ "@rollup/rollup-win32-x64-gnu": "4.60.3",
+ "@rollup/rollup-win32-x64-msvc": "4.60.3",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz",
+ "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "get-intrinsic": "^1.3.0",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/sass": {
+ "version": "1.99.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz",
+ "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^5.1.5",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
+ "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true,
+ "license": "CC-BY-3.0"
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz",
+ "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/speakingurl": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "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/stylelint": {
+ "version": "16.26.1",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz",
+ "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/stylelint"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-syntax-patches-for-csstree": "^1.0.19",
+ "@csstools/css-tokenizer": "^3.0.4",
+ "@csstools/media-query-list-parser": "^4.0.3",
+ "@csstools/selector-specificity": "^5.0.0",
+ "@dual-bundle/import-meta-resolve": "^4.2.1",
+ "balanced-match": "^2.0.0",
+ "colord": "^2.9.3",
+ "cosmiconfig": "^9.0.0",
+ "css-functions-list": "^3.2.3",
+ "css-tree": "^3.1.0",
+ "debug": "^4.4.3",
+ "fast-glob": "^3.3.3",
+ "fastest-levenshtein": "^1.0.16",
+ "file-entry-cache": "^11.1.1",
+ "global-modules": "^2.0.0",
+ "globby": "^11.1.0",
+ "globjoin": "^0.1.4",
+ "html-tags": "^3.3.1",
+ "ignore": "^7.0.5",
+ "imurmurhash": "^0.1.4",
+ "is-plain-object": "^5.0.0",
+ "known-css-properties": "^0.37.0",
+ "mathml-tag-names": "^2.1.3",
+ "meow": "^13.2.0",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.5.6",
+ "postcss-resolve-nested-selector": "^0.1.6",
+ "postcss-safe-parser": "^7.0.1",
+ "postcss-selector-parser": "^7.1.0",
+ "postcss-value-parser": "^4.2.0",
+ "resolve-from": "^5.0.0",
+ "string-width": "^4.2.3",
+ "supports-hyperlinks": "^3.2.0",
+ "svg-tags": "^1.0.0",
+ "table": "^6.9.0",
+ "write-file-atomic": "^5.0.1"
+ },
+ "bin": {
+ "stylelint": "bin/stylelint.mjs"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ }
+ },
+ "node_modules/stylelint-config-html": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-html/-/stylelint-config-html-1.1.0.tgz",
+ "integrity": "sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12 || >=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ota-meshi"
+ },
+ "peerDependencies": {
+ "postcss-html": "^1.0.0",
+ "stylelint": ">=14.0.0"
+ }
+ },
+ "node_modules/stylelint-config-recommended": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz",
+ "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/stylelint"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "peerDependencies": {
+ "stylelint": "^16.1.0"
+ }
+ },
+ "node_modules/stylelint-config-recommended-scss": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz",
+ "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-scss": "^4.0.9",
+ "stylelint-config-recommended": "^14.0.1",
+ "stylelint-scss": "^6.4.0"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3.3",
+ "stylelint": "^16.6.1"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/stylelint-config-standard": {
+ "version": "35.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-35.0.0.tgz",
+ "integrity": "sha512-JyQrNZk2BZwVKFauGGxW2U6RuhIfQ4XoHHo+rBzMHcAkLnwI/knpszwXjzxiMgSfcxbZBckM7Vq4LHoANTR85g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "stylelint-config-recommended": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "peerDependencies": {
+ "stylelint": "^16.0.0"
+ }
+ },
+ "node_modules/stylelint-config-standard-scss": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-12.0.0.tgz",
+ "integrity": "sha512-ATh3EcEOLZq0iwlFaBdIsSavrla0lNtJ7mO7hdE7DgVT6imozRggFSqd4cFcjzVnOLKv/uJT63MmqA1acIflbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "stylelint-config-recommended-scss": "^14.0.0",
+ "stylelint-config-standard": "^35.0.0"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3.3",
+ "stylelint": "^16.0.2"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/stylelint-declaration-block-no-ignored-properties": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/stylelint-declaration-block-no-ignored-properties/-/stylelint-declaration-block-no-ignored-properties-2.8.0.tgz",
+ "integrity": "sha512-Ws8Cav7Y+SPN0JsV407LrnNXWOrqGjxShf+37GBtnU/C58Syve9c0+I/xpLcFOosST3ternykn3Lp77f3ITnFw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "stylelint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+ }
+ },
+ "node_modules/stylelint-scss": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz",
+ "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "^3.0.1",
+ "is-plain-object": "^5.0.0",
+ "known-css-properties": "^0.37.0",
+ "mdn-data": "^2.25.0",
+ "postcss-media-query-parser": "^0.2.3",
+ "postcss-resolve-nested-selector": "^0.1.6",
+ "postcss-selector-parser": "^7.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "peerDependencies": {
+ "stylelint": "^16.8.2"
+ }
+ },
+ "node_modules/stylelint-scss/node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/stylelint/node_modules/@csstools/selector-specificity": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
+ "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "postcss-selector-parser": "^7.0.0"
+ }
+ },
+ "node_modules/stylelint/node_modules/balanced-match": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
+ "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/stylelint/node_modules/file-entry-cache": {
+ "version": "11.1.3",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.3.tgz",
+ "integrity": "sha512-oMbq0PD6VIiIwMF6LIa7MEwd/l9huKwmqRKXqmrkqIZv8CvRbfowL+L0ryAl8h//HfAS0zS+4SbYoRyAoA6BJA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^6.1.22"
+ }
+ },
+ "node_modules/stylelint/node_modules/flat-cache": {
+ "version": "6.1.22",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.22.tgz",
+ "integrity": "sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cacheable": "^2.3.4",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
+ }
+ },
+ "node_modules/stylelint/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/stylelint/node_modules/postcss-safe-parser": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz",
+ "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.31"
+ }
+ },
+ "node_modules/stylelint/node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/stylelint/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/superjson": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
+ "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "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/supports-hyperlinks": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz",
+ "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/svg-tags": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
+ "dev": true
+ },
+ "node_modules/svgo": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz",
+ "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^7.2.0",
+ "css-select": "^5.1.0",
+ "css-tree": "^2.3.1",
+ "css-what": "^6.1.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.0.0",
+ "sax": "^1.5.0"
+ },
+ "bin": {
+ "svgo": "bin/svgo"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/svgo/node_modules/css-tree": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
+ "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.30",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/svgo/node_modules/mdn-data": {
+ "version": "2.0.30",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
+ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/table": {
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz",
+ "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/table/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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-case": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
+ "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
+ "license": "MIT"
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "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": "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/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "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/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz",
+ "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-svg-loader": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-5.1.1.tgz",
+ "integrity": "sha512-RPzcXA/EpKJA0585x58DBgs7my2VfeJ+j2j1EoHY4Zh82Y7hV4cR1fElgy2aZi85+QSrcLLoTStQ5uZjD68u+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "svgo": "^3.3.3"
+ },
+ "peerDependencies": {
+ "vue": ">=3.2.13"
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz",
+ "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.34",
+ "@vue/compiler-sfc": "3.5.34",
+ "@vue/runtime-dom": "3.5.34",
+ "@vue/server-renderer": "3.5.34",
+ "@vue/shared": "3.5.34"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue-advanced-cropper": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/vue-advanced-cropper/-/vue-advanced-cropper-2.8.9.tgz",
+ "integrity": "sha512-1jc5gO674kVGpJKekoaol6ZlwaF5VYDLSBwBOUpViW0IOrrRsyLw6XNszjEqgbavvqinlKNS6Kqlom3B5M72Tw==",
+ "license": "MIT",
+ "dependencies": {
+ "classnames": "^2.2.6",
+ "debounce": "^1.2.0",
+ "easy-bem": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ },
+ "peerDependencies": {
+ "vue": "^3.0.0"
+ }
+ },
+ "node_modules/vue-eslint-parser": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz",
+ "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "eslint-scope": "^8.2.0 || ^9.0.0",
+ "eslint-visitor-keys": "^4.2.0 || ^5.0.0",
+ "espree": "^10.3.0 || ^11.0.0",
+ "esquery": "^1.6.0",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
+ "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@types/esrecurse": "^4.3.1",
+ "@types/estree": "^1.0.8",
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/espree": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+ "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.16.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^5.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/semver": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
+ "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/vue-router": {
+ "version": "4.6.4",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
+ "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-api": "^6.6.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "vue": "^3.5.0"
+ }
+ },
+ "node_modules/vue3-persian-datetime-picker": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/vue3-persian-datetime-picker/-/vue3-persian-datetime-picker-1.2.2.tgz",
+ "integrity": "sha512-d7nkj5vgtUvEXZboSdRmP1uwBfXvXgXqdvsOOMQb34jiMZU/aBDrTYWTEe1N+XKF9pvTTJn8Rws9ttJmyhK/hw==",
+ "license": "MIT",
+ "dependencies": {
+ "moment-jalaali": "^0.9.4"
+ }
+ },
+ "node_modules/vue3-toastify": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/vue3-toastify/-/vue3-toastify-0.2.9.tgz",
+ "integrity": "sha512-LN2GJGKgjt+C6IIBANp9hCM2A4yc5jC2Kj4YGl1J7ptj4rhThOJOGGlkCg+IxDt7hntNw9n3MG9ifv/AymyxKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20",
+ "npm": ">=9.0.0"
+ },
+ "peerDependencies": {
+ "vue": ">=3.2.0"
+ },
+ "peerDependenciesMeta": {
+ "vue": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
+ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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/yup": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz",
+ "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==",
+ "license": "MIT",
+ "dependencies": {
+ "property-expr": "^2.0.5",
+ "tiny-case": "^1.0.3",
+ "toposort": "^2.0.2",
+ "type-fest": "^2.19.0"
+ }
+ },
+ "node_modules/yup/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d609ae3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "banu-front",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview",
+ "lint": "eslint . --ext .js,.vue --max-warnings=0",
+ "lint:fix": "eslint . --ext .js,.vue --fix --max-warnings=0",
+ "lint:css:check": "stylelint \"src/**/*.{css,scss,vue}\" --max-warnings=0",
+ "lint:css:fix": "stylelint \"src/**/*.{css,scss,vue}\" --fix --max-warnings=0",
+ "format": "prettier --write .",
+ "format:check": "prettier --check ."
+ },
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.6",
+ "@tanstack/vue-query": "^5.62.2",
+ "@tanstack/vue-query-devtools": "^5.62.2",
+ "axios": "^1.12.2",
+ "lodash": "^4.18.1",
+ "pinia": "^3.0.3",
+ "vue": "^3.5.21",
+ "vue-advanced-cropper": "^2.8.9",
+ "vue-router": "^4.5.1",
+ "vue3-persian-datetime-picker": "^1.2.2",
+ "vue3-toastify": "^0.2.5",
+ "yup": "^1.7.0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^6.0.1",
+ "eslint": "^8.57.0",
+ "eslint-config-prettier": "^8.10.2",
+ "eslint-plugin-import": "^2.32.0",
+ "eslint-plugin-prettier": "^4.2.1",
+ "eslint-plugin-unicorn": "^55.0.0",
+ "eslint-plugin-vue": "^9.15.1",
+ "postcss-html": "^1.8.0",
+ "prettier": "2.8.8",
+ "sass": "^1.83.0",
+ "stylelint": "^16.0.0",
+ "stylelint-config-html": "^1.1.0",
+ "stylelint-config-standard-scss": "^12.0.0",
+ "stylelint-declaration-block-no-ignored-properties": "^2.8.0",
+ "vite": "^7.1.6",
+ "vite-svg-loader": "^5.1.0",
+ "vue-eslint-parser": "^10.2.0"
+ }
+}
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..f2115d8
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/src/assets/fonts/aria/AriaWeb-Normal.woff2 b/src/assets/fonts/aria/AriaWeb-Normal.woff2
new file mode 100644
index 0000000..3277534
Binary files /dev/null and b/src/assets/fonts/aria/AriaWeb-Normal.woff2 differ
diff --git a/src/assets/fonts/aria/AriaWebFaNum-Light.woff2 b/src/assets/fonts/aria/AriaWebFaNum-Light.woff2
new file mode 100644
index 0000000..abf1905
Binary files /dev/null and b/src/assets/fonts/aria/AriaWebFaNum-Light.woff2 differ
diff --git a/src/assets/fonts/aria/AriaWebFaNum-Medium.woff2 b/src/assets/fonts/aria/AriaWebFaNum-Medium.woff2
new file mode 100644
index 0000000..ed43173
Binary files /dev/null and b/src/assets/fonts/aria/AriaWebFaNum-Medium.woff2 differ
diff --git a/src/assets/fonts/aria/AriaWebFaNum-Regular.woff2 b/src/assets/fonts/aria/AriaWebFaNum-Regular.woff2
new file mode 100644
index 0000000..81db53c
Binary files /dev/null and b/src/assets/fonts/aria/AriaWebFaNum-Regular.woff2 differ
diff --git a/src/assets/fonts/aria/AriaWebFaNum-SemiBold.woff2 b/src/assets/fonts/aria/AriaWebFaNum-SemiBold.woff2
new file mode 100644
index 0000000..c65caa3
Binary files /dev/null and b/src/assets/fonts/aria/AriaWebFaNum-SemiBold.woff2 differ
diff --git a/src/assets/fonts/iran-yekan/iranyekanwebboldfanum.woff b/src/assets/fonts/iran-yekan/iranyekanwebboldfanum.woff
new file mode 100644
index 0000000..07f9756
Binary files /dev/null and b/src/assets/fonts/iran-yekan/iranyekanwebboldfanum.woff differ
diff --git a/src/assets/fonts/iran-yekan/iranyekanweblightfanum.woff b/src/assets/fonts/iran-yekan/iranyekanweblightfanum.woff
new file mode 100644
index 0000000..9e6d42c
Binary files /dev/null and b/src/assets/fonts/iran-yekan/iranyekanweblightfanum.woff differ
diff --git a/src/assets/fonts/iran-yekan/iranyekanwebmediumfanum.woff b/src/assets/fonts/iran-yekan/iranyekanwebmediumfanum.woff
new file mode 100644
index 0000000..8fe8e40
Binary files /dev/null and b/src/assets/fonts/iran-yekan/iranyekanwebmediumfanum.woff differ
diff --git a/src/assets/fonts/iran-yekan/iranyekanwebregularfanum.woff b/src/assets/fonts/iran-yekan/iranyekanwebregularfanum.woff
new file mode 100644
index 0000000..3a07dcc
Binary files /dev/null and b/src/assets/fonts/iran-yekan/iranyekanwebregularfanum.woff differ
diff --git a/src/assets/fonts/montserrat/Montserrat-ExtraLight.ttf b/src/assets/fonts/montserrat/Montserrat-ExtraLight.ttf
new file mode 100644
index 0000000..efaeab0
Binary files /dev/null and b/src/assets/fonts/montserrat/Montserrat-ExtraLight.ttf differ
diff --git a/src/assets/fonts/montserrat/Montserrat-Regular.ttf b/src/assets/fonts/montserrat/Montserrat-Regular.ttf
new file mode 100644
index 0000000..895e220
Binary files /dev/null and b/src/assets/fonts/montserrat/Montserrat-Regular.ttf differ
diff --git a/src/assets/icons/arrow-left.svg b/src/assets/icons/arrow-left.svg
new file mode 100644
index 0000000..c6e77ac
--- /dev/null
+++ b/src/assets/icons/arrow-left.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/arrows-clockwise.svg b/src/assets/icons/arrows-clockwise.svg
new file mode 100644
index 0000000..4ebe3ea
--- /dev/null
+++ b/src/assets/icons/arrows-clockwise.svg
@@ -0,0 +1,13 @@
+
diff --git a/src/assets/icons/attach-file.svg b/src/assets/icons/attach-file.svg
new file mode 100644
index 0000000..63ac2fb
--- /dev/null
+++ b/src/assets/icons/attach-file.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/bell.svg b/src/assets/icons/bell.svg
new file mode 100644
index 0000000..abbbb7f
--- /dev/null
+++ b/src/assets/icons/bell.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/book.svg b/src/assets/icons/book.svg
new file mode 100644
index 0000000..4c78921
--- /dev/null
+++ b/src/assets/icons/book.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/calendar.svg b/src/assets/icons/calendar.svg
new file mode 100644
index 0000000..3deee4b
--- /dev/null
+++ b/src/assets/icons/calendar.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/caret-down.svg b/src/assets/icons/caret-down.svg
new file mode 100644
index 0000000..2f20d72
--- /dev/null
+++ b/src/assets/icons/caret-down.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/caret-left.svg b/src/assets/icons/caret-left.svg
new file mode 100644
index 0000000..8c68654
--- /dev/null
+++ b/src/assets/icons/caret-left.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/caret-right.svg b/src/assets/icons/caret-right.svg
new file mode 100644
index 0000000..fdd61e9
--- /dev/null
+++ b/src/assets/icons/caret-right.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/chat.svg b/src/assets/icons/chat.svg
new file mode 100644
index 0000000..6f6468c
--- /dev/null
+++ b/src/assets/icons/chat.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/check-square.svg b/src/assets/icons/check-square.svg
new file mode 100644
index 0000000..06b3816
--- /dev/null
+++ b/src/assets/icons/check-square.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/check.svg b/src/assets/icons/check.svg
new file mode 100644
index 0000000..a5f81f3
--- /dev/null
+++ b/src/assets/icons/check.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/close.svg b/src/assets/icons/close.svg
new file mode 100644
index 0000000..1840059
--- /dev/null
+++ b/src/assets/icons/close.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/copy.svg b/src/assets/icons/copy.svg
new file mode 100644
index 0000000..b5d0ec8
--- /dev/null
+++ b/src/assets/icons/copy.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/eye-slash.svg b/src/assets/icons/eye-slash.svg
new file mode 100644
index 0000000..2ea7be0
--- /dev/null
+++ b/src/assets/icons/eye-slash.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/eye.svg b/src/assets/icons/eye.svg
new file mode 100644
index 0000000..4b9234b
--- /dev/null
+++ b/src/assets/icons/eye.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/file.svg b/src/assets/icons/file.svg
new file mode 100644
index 0000000..ca92599
--- /dev/null
+++ b/src/assets/icons/file.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/funnel.svg b/src/assets/icons/funnel.svg
new file mode 100644
index 0000000..f69ba91
--- /dev/null
+++ b/src/assets/icons/funnel.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/instagram.svg b/src/assets/icons/instagram.svg
new file mode 100644
index 0000000..bc96434
--- /dev/null
+++ b/src/assets/icons/instagram.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/list-bullets.svg b/src/assets/icons/list-bullets.svg
new file mode 100644
index 0000000..e8525bd
--- /dev/null
+++ b/src/assets/icons/list-bullets.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/menu.svg b/src/assets/icons/menu.svg
new file mode 100644
index 0000000..2d7d464
--- /dev/null
+++ b/src/assets/icons/menu.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/mood.svg b/src/assets/icons/mood.svg
new file mode 100644
index 0000000..e146bf6
--- /dev/null
+++ b/src/assets/icons/mood.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/paper-plane-right.svg b/src/assets/icons/paper-plane-right.svg
new file mode 100644
index 0000000..64b1606
--- /dev/null
+++ b/src/assets/icons/paper-plane-right.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/assets/icons/paper-plane.svg b/src/assets/icons/paper-plane.svg
new file mode 100644
index 0000000..ead9b34
--- /dev/null
+++ b/src/assets/icons/paper-plane.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/pencil.svg b/src/assets/icons/pencil.svg
new file mode 100644
index 0000000..a3a92c3
--- /dev/null
+++ b/src/assets/icons/pencil.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/phone.svg b/src/assets/icons/phone.svg
new file mode 100644
index 0000000..425d846
--- /dev/null
+++ b/src/assets/icons/phone.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/plus.svg b/src/assets/icons/plus.svg
new file mode 100644
index 0000000..a29a38b
--- /dev/null
+++ b/src/assets/icons/plus.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/spinner.svg b/src/assets/icons/spinner.svg
new file mode 100644
index 0000000..d83d1d3
--- /dev/null
+++ b/src/assets/icons/spinner.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/square.svg b/src/assets/icons/square.svg
new file mode 100644
index 0000000..cee8264
--- /dev/null
+++ b/src/assets/icons/square.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/telegram.svg b/src/assets/icons/telegram.svg
new file mode 100644
index 0000000..a90002a
--- /dev/null
+++ b/src/assets/icons/telegram.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/trash.svg b/src/assets/icons/trash.svg
new file mode 100644
index 0000000..2abc5eb
--- /dev/null
+++ b/src/assets/icons/trash.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/upload.svg b/src/assets/icons/upload.svg
new file mode 100644
index 0000000..cc73423
--- /dev/null
+++ b/src/assets/icons/upload.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/user.svg b/src/assets/icons/user.svg
new file mode 100644
index 0000000..a362ed2
--- /dev/null
+++ b/src/assets/icons/user.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/users-three.svg b/src/assets/icons/users-three.svg
new file mode 100644
index 0000000..d45a6df
--- /dev/null
+++ b/src/assets/icons/users-three.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/users.svg b/src/assets/icons/users.svg
new file mode 100644
index 0000000..0b80c58
--- /dev/null
+++ b/src/assets/icons/users.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/warning.svg b/src/assets/icons/warning.svg
new file mode 100644
index 0000000..9376696
--- /dev/null
+++ b/src/assets/icons/warning.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/images/auth/auth-logo.png b/src/assets/images/auth/auth-logo.png
new file mode 100644
index 0000000..b735fd6
Binary files /dev/null and b/src/assets/images/auth/auth-logo.png differ
diff --git a/src/assets/images/auth/flower.png b/src/assets/images/auth/flower.png
new file mode 100644
index 0000000..86ae1ff
Binary files /dev/null and b/src/assets/images/auth/flower.png differ
diff --git a/src/assets/images/auth/login-pattern-logo.jpg b/src/assets/images/auth/login-pattern-logo.jpg
new file mode 100644
index 0000000..8e50318
Binary files /dev/null and b/src/assets/images/auth/login-pattern-logo.jpg differ
diff --git a/src/assets/images/auth/login-pattern-mobile.png b/src/assets/images/auth/login-pattern-mobile.png
new file mode 100644
index 0000000..d059eea
Binary files /dev/null and b/src/assets/images/auth/login-pattern-mobile.png differ
diff --git a/src/assets/images/auth/login-pattern.jpg b/src/assets/images/auth/login-pattern.jpg
new file mode 100644
index 0000000..6cf27c9
Binary files /dev/null and b/src/assets/images/auth/login-pattern.jpg differ
diff --git a/src/assets/images/cover.png b/src/assets/images/cover.png
new file mode 100644
index 0000000..71c0b23
Binary files /dev/null and b/src/assets/images/cover.png differ
diff --git a/src/assets/images/logo-pinkish-red.png b/src/assets/images/logo-pinkish-red.png
new file mode 100644
index 0000000..c4b6ace
Binary files /dev/null and b/src/assets/images/logo-pinkish-red.png differ
diff --git a/src/assets/images/logo-white.png b/src/assets/images/logo-white.png
new file mode 100644
index 0000000..288da42
Binary files /dev/null and b/src/assets/images/logo-white.png differ
diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png
new file mode 100644
index 0000000..5a84f0a
Binary files /dev/null and b/src/assets/images/logo.png differ
diff --git a/src/assets/main.scss b/src/assets/main.scss
new file mode 100644
index 0000000..0bf3384
--- /dev/null
+++ b/src/assets/main.scss
@@ -0,0 +1,7 @@
+@use './styles/colors';
+@use './styles/variables';
+@use './styles/reset';
+@use './styles/typography';
+@use './styles/forms';
+@use './styles/modals';
+@use './styles/datepicker';
diff --git a/src/assets/styles/_colors.scss b/src/assets/styles/_colors.scss
new file mode 100644
index 0000000..d52b8b4
--- /dev/null
+++ b/src/assets/styles/_colors.scss
@@ -0,0 +1,25 @@
+$primary: #f36675;
+$secondary: #007074;
+$error: #cc2831;
+$validate: #a2eaa8;
+$prim-gray: #818181;
+$sec-gray: #5d5d5d;
+$thd-gray: #ddd;
+$prim-text: #000;
+$body-text: #5f5f5f;
+$body-bg: #fff;
+$scrollbar-thumb: #d1d5db;
+$scrollbar-thumb-hover: #9ca3af;
+
+:root {
+ --color-primary: #{$primary};
+ --color-secondary: #{$secondary};
+ --color-error: #{$error};
+ --color-validate: #{$validate};
+ --color-prim-gray: #{$prim-gray};
+ --color-sec-gray: #{$sec-gray};
+ --color-thd-gray: #{$thd-gray};
+ --color-prim-text: #{$prim-text};
+ --text-color: #{$body-text};
+ --bg-color: #{$body-bg};
+}
diff --git a/src/assets/styles/_datepicker.scss b/src/assets/styles/_datepicker.scss
new file mode 100644
index 0000000..88dd95c
--- /dev/null
+++ b/src/assets/styles/_datepicker.scss
@@ -0,0 +1,109 @@
+.date-picker-dropdown {
+ .vpd-main .vpd-input-group {
+ display: none;
+ }
+
+ .vpd-wrapper .vpd-container {
+ margin: 0 !important;
+ font-family: iran-yekan;
+ width: 100%;
+ }
+
+ .vpd-wrapper .vpd-content {
+ width: auto;
+ border-radius: 8px;
+ }
+
+ .vpd-wrapper .vpd-header .vpd-date {
+ display: none;
+ }
+
+ .vpd-wrapper .vpd-header {
+ background-color: transparent !important;
+ padding: 5px;
+ }
+
+ .vpd-wrapper .vpd-header .vpd-year-label {
+ color: #5f5f5f;
+ text-align: center;
+ }
+
+ .vpd-wrapper .vpd-body {
+ overflow-x: hidden;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-controls button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-clearfix.vpd-week {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-clearfix.vpd-week .vpd-weekday {
+ width: auto;
+ float: none;
+ clear: both;
+ padding: 0 12px;
+ }
+
+ @media screen and (max-width: 400px) {
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-clearfix.vpd-week,
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-days {
+ padding: 0 5px;
+ }
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-days .direction-prev .vpd-clearfix {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-days {
+ height: fit-content !important;
+ padding: 0 12px;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-days .vpd-day {
+ width: 35px;
+ height: 35px;
+ float: right;
+ line-height: 35px;
+ }
+
+ .vpd-wrapper
+ .vpd-body
+ .vpd-clearfix.vpd-month
+ .vpd-days
+ .vpd-day:not([disabled='true']).vpd-selected
+ .vpd-day-effect,
+ .vpd-wrapper
+ .vpd-body
+ .vpd-clearfix.vpd-month
+ .vpd-days
+ .vpd-day:not([disabled='true']):hover
+ .vpd-day-effect {
+ background-color: #f36675 !important;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-clearfix.vpd-month .vpd-days .vpd-day .vpd-day-effect {
+ width: 35px;
+ height: 35px;
+ top: -2px;
+ left: 0;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-close-addon {
+ background-color: #f5f5f5;
+ border-radius: 5px;
+ }
+
+ .vpd-wrapper .vpd-body .vpd-month-label {
+ width: auto;
+ }
+}
diff --git a/src/assets/styles/_forms.scss b/src/assets/styles/_forms.scss
new file mode 100644
index 0000000..7e7a69e
--- /dev/null
+++ b/src/assets/styles/_forms.scss
@@ -0,0 +1,20 @@
+@keyframes shake {
+ 0%,
+ 100% {
+ transform: translateX(0);
+ }
+
+ 20%,
+ 80% {
+ transform: translateX(-2px);
+ }
+
+ 40%,
+ 60% {
+ transform: translateX(2px);
+ }
+}
+
+.animate-shake {
+ animation: shake 0.5s ease-in-out;
+}
diff --git a/src/assets/styles/_modals.scss b/src/assets/styles/_modals.scss
new file mode 100644
index 0000000..2953122
--- /dev/null
+++ b/src/assets/styles/_modals.scss
@@ -0,0 +1,24 @@
+.slide-drawer-enter-active,
+.slide-drawer-leave-active {
+ transition: transform 0.3s ease;
+}
+
+.slide-drawer-enter-from,
+.slide-drawer-leave-to {
+ transform: translateX(100%);
+}
+
+.slide-drawer-enter-to,
+.slide-drawer-leave-from {
+ transform: translateX(0);
+}
+
+.fade-enter-active,
+.fade-leave-active {
+ transition: opacity 0.2s ease;
+}
+
+.fade-enter-from,
+.fade-leave-to {
+ opacity: 0;
+}
diff --git a/src/assets/styles/_reset.scss b/src/assets/styles/_reset.scss
new file mode 100644
index 0000000..0fbc321
--- /dev/null
+++ b/src/assets/styles/_reset.scss
@@ -0,0 +1,58 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0 !important;
+ padding: 0 !important;
+ font-family: var(--font-family-primary), sans-serif;
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ overflow-x: hidden;
+}
+
+.dir-rtl {
+ direction: rtl;
+}
+
+.scrollbar-thin {
+ -webkit-overflow-scrolling: touch;
+ scrollbar-width: thin;
+ scrollbar-color: #d1d5db transparent;
+}
+
+.scrollbar-thin::-webkit-scrollbar {
+ width: 3px;
+ height: 3px;
+}
+
+.scrollbar-thin::-webkit-scrollbar-track {
+ background: transparent;
+ border-radius: 10px;
+}
+
+.scrollbar-thin::-webkit-scrollbar-thumb {
+ background: #d1d5db;
+ border-radius: 10px;
+}
+
+.scrollbar-thin::-webkit-scrollbar-thumb:hover {
+ background: #9ca3af;
+}
+
+@keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.animate-spin {
+ animation: spin 1s linear infinite;
+ transform-origin: center;
+}
diff --git a/src/assets/styles/_typography.scss b/src/assets/styles/_typography.scss
new file mode 100644
index 0000000..ffbdf7e
--- /dev/null
+++ b/src/assets/styles/_typography.scss
@@ -0,0 +1,87 @@
+@font-face {
+ font-family: montserrat;
+ src: url('../fonts/montserrat/Montserrat-ExtraLight.ttf') format('truetype');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: montserrat;
+ src: url('../fonts/montserrat/Montserrat-Regular.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: aria;
+ src: url('../fonts/aria/AriaWebFaNum-Light.woff2') format('woff2');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: aria;
+ src: url('../fonts/aria/AriaWebFaNum-Regular.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: aria;
+ src: url('../fonts/aria/AriaWebFaNum-Medium.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: aria;
+ src: url('../fonts/aria/AriaWebFaNum-SemiBold.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: aria;
+ src: url('../fonts/aria/AriaWeb-Normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: iran-yekan;
+ src: url('../fonts/iran-yekan/iranyekanwebregularfanum.woff') format('woff');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: iran-yekan;
+ src: url('../fonts/iran-yekan/iranyekanwebmediumfanum.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: iran-yekan;
+ src: url('../fonts/iran-yekan/iranyekanwebboldfanum.woff') format('woff');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: iran-yekan;
+ src: url('../fonts/iran-yekan/iranyekanweblightfanum.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
diff --git a/src/assets/styles/_variables.scss b/src/assets/styles/_variables.scss
new file mode 100644
index 0000000..87d4742
--- /dev/null
+++ b/src/assets/styles/_variables.scss
@@ -0,0 +1,36 @@
+$font-fa: 'aria', 'Tahoma', sans-serif;
+$font-number-fa: 'iran-yekan', 'aria', sans-serif;
+$font-en: 'montserrat', 'Tahoma', sans-serif;
+$font-size-en-xs: 0.625rem;
+$font-size-2xs: 0.6875rem;
+$font-size-xxs: 0.75rem;
+$font-size-label: 0.8125rem;
+$font-size-input: 0.9375rem;
+$font-size-xxl: 2.0625rem;
+$input-height: 2.5rem;
+$input-height-lg: 3.125rem;
+$icon-xs: 1.0625rem;
+$icon-sm: 1.375rem;
+$icon-lg: 1.875rem;
+$icon-xl: 2.125rem;
+$icon-2xl: 3.375rem;
+
+:root {
+ --font-family-primary: 'aria';
+ --font-family-fa: #{$font-fa};
+ --font-family-number-fa: #{$font-number-fa};
+ --font-family-en: #{$font-en};
+ --font-size-en-xs: #{$font-size-en-xs};
+ --font-size-2xs: #{$font-size-2xs};
+ --font-size-xxs: #{$font-size-xxs};
+ --font-size-label: #{$font-size-label};
+ --font-size-input: #{$font-size-input};
+ --font-size-xxl: #{$font-size-xxl};
+ --input-height: #{$input-height};
+ --input-height-lg: #{$input-height-lg};
+ --icon-xs: #{$icon-xs};
+ --icon-sm: #{$icon-sm};
+ --icon-lg: #{$icon-lg};
+ --icon-xl: #{$icon-xl};
+ --icon-2xl: #{$icon-2xl};
+}
diff --git a/src/components/BaseButton.vue b/src/components/BaseButton.vue
new file mode 100644
index 0000000..f203790
--- /dev/null
+++ b/src/components/BaseButton.vue
@@ -0,0 +1,125 @@
+
+
+
+ {{ text }}
+
+
+
+
+
+
+
+
diff --git a/src/components/BasicModal.vue b/src/components/BasicModal.vue
new file mode 100644
index 0000000..07b42b6
--- /dev/null
+++ b/src/components/BasicModal.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/CircleButton.vue b/src/components/CircleButton.vue
new file mode 100644
index 0000000..5a4d820
--- /dev/null
+++ b/src/components/CircleButton.vue
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ConfirmModal.vue b/src/components/ConfirmModal.vue
new file mode 100644
index 0000000..f53487f
--- /dev/null
+++ b/src/components/ConfirmModal.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
{{ data?.title || 'تأیید حذف' }}
+
+
+
+ این عمل غیرقابل بازگشت است. آیا از حذف اطمینان دارید؟
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Copyright.vue b/src/components/Copyright.vue
new file mode 100644
index 0000000..c08e0d2
--- /dev/null
+++ b/src/components/Copyright.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
diff --git a/src/components/DropdownMenu.vue b/src/components/DropdownMenu.vue
new file mode 100644
index 0000000..333e8dd
--- /dev/null
+++ b/src/components/DropdownMenu.vue
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/HeaderBlock.vue b/src/components/HeaderBlock.vue
new file mode 100644
index 0000000..66e1c6b
--- /dev/null
+++ b/src/components/HeaderBlock.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
diff --git a/src/components/LineTitleBlock.vue b/src/components/LineTitleBlock.vue
new file mode 100644
index 0000000..b89dfb0
--- /dev/null
+++ b/src/components/LineTitleBlock.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
{{ title }}
+
{{ titleEn }}
+
+
+
+
+
+
+
diff --git a/src/components/blocks/BoxedIconTitleBlock.vue b/src/components/blocks/BoxedIconTitleBlock.vue
new file mode 100644
index 0000000..45d0448
--- /dev/null
+++ b/src/components/blocks/BoxedIconTitleBlock.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
{{ title }}
+
{{ desc }}
+
+
+
+
+
+
+
diff --git a/src/components/blocks/LineInfoBlock.vue b/src/components/blocks/LineInfoBlock.vue
new file mode 100644
index 0000000..463210a
--- /dev/null
+++ b/src/components/blocks/LineInfoBlock.vue
@@ -0,0 +1,69 @@
+
+
+
+
{{ title }}
+
+ {{ numericDesc }}
+ {{ desc }}
+
+
+
+
+
+
+
diff --git a/src/components/blocks/NoItems.vue b/src/components/blocks/NoItems.vue
new file mode 100644
index 0000000..4728d6c
--- /dev/null
+++ b/src/components/blocks/NoItems.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
{{ title }}
+
{{ desc }}
+
+
+
+
+
+
+
diff --git a/src/components/blocks/PaginationBlock.vue b/src/components/blocks/PaginationBlock.vue
new file mode 100644
index 0000000..e71dc4b
--- /dev/null
+++ b/src/components/blocks/PaginationBlock.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
diff --git a/src/components/blocks/SimpleTitleIconBlock.vue b/src/components/blocks/SimpleTitleIconBlock.vue
new file mode 100644
index 0000000..df1c32b
--- /dev/null
+++ b/src/components/blocks/SimpleTitleIconBlock.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/src/components/blocks/SkeletonLoaderBlock.vue b/src/components/blocks/SkeletonLoaderBlock.vue
new file mode 100644
index 0000000..6b9cd11
--- /dev/null
+++ b/src/components/blocks/SkeletonLoaderBlock.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
diff --git a/src/components/blocks/TabsBlock.vue b/src/components/blocks/TabsBlock.vue
new file mode 100644
index 0000000..70d8cfa
--- /dev/null
+++ b/src/components/blocks/TabsBlock.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/form/AutocompleteField.vue b/src/components/form/AutocompleteField.vue
new file mode 100644
index 0000000..3c15cc1
--- /dev/null
+++ b/src/components/form/AutocompleteField.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/components/form/DatePickerField.vue b/src/components/form/DatePickerField.vue
new file mode 100644
index 0000000..fdb2cc8
--- /dev/null
+++ b/src/components/form/DatePickerField.vue
@@ -0,0 +1,257 @@
+
+
+
+
+
+ {{ displayValue }}
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/form/FileUploader.vue b/src/components/form/FileUploader.vue
new file mode 100644
index 0000000..f8c43cd
--- /dev/null
+++ b/src/components/form/FileUploader.vue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
هیچ فایلی آپلود نشده است
+
+
+
+
+
+
diff --git a/src/components/form/ImageCropper.vue b/src/components/form/ImageCropper.vue
new file mode 100644
index 0000000..cfc5f28
--- /dev/null
+++ b/src/components/form/ImageCropper.vue
@@ -0,0 +1,357 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
diff --git a/src/components/form/PasswordField.vue b/src/components/form/PasswordField.vue
new file mode 100644
index 0000000..833022f
--- /dev/null
+++ b/src/components/form/PasswordField.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/form/SelectField.vue b/src/components/form/SelectField.vue
new file mode 100644
index 0000000..f84db29
--- /dev/null
+++ b/src/components/form/SelectField.vue
@@ -0,0 +1,377 @@
+
+
+
+
+
+ {{ selectedLabel }}
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/form/TextField.vue b/src/components/form/TextField.vue
new file mode 100644
index 0000000..c762fab
--- /dev/null
+++ b/src/components/form/TextField.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
diff --git a/src/components/form/TextareaField.vue b/src/components/form/TextareaField.vue
new file mode 100644
index 0000000..9039bd3
--- /dev/null
+++ b/src/components/form/TextareaField.vue
@@ -0,0 +1,189 @@
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
diff --git a/src/components/form/ToggleSwitch.vue b/src/components/form/ToggleSwitch.vue
new file mode 100644
index 0000000..1cdfd52
--- /dev/null
+++ b/src/components/form/ToggleSwitch.vue
@@ -0,0 +1,107 @@
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
diff --git a/src/components/icons/SvgIcon.vue b/src/components/icons/SvgIcon.vue
new file mode 100644
index 0000000..4bdac10
--- /dev/null
+++ b/src/components/icons/SvgIcon.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
diff --git a/src/components/icons/registry.js b/src/components/icons/registry.js
new file mode 100644
index 0000000..0dadfa8
--- /dev/null
+++ b/src/components/icons/registry.js
@@ -0,0 +1,10 @@
+const modules = import.meta.glob('@/assets/icons/*.svg', { eager: true })
+
+export const iconRegistry = Object.fromEntries(
+ Object.entries(modules).map(([path, mod]) => {
+ const name = path.split('/').pop().replace('.svg', '')
+ return [name, mod.default]
+ })
+)
+
+export const iconNames = Object.keys(iconRegistry)
diff --git a/src/composables/useAuth.js b/src/composables/useAuth.js
new file mode 100644
index 0000000..0ef604e
--- /dev/null
+++ b/src/composables/useAuth.js
@@ -0,0 +1,36 @@
+import { storeToRefs } from 'pinia'
+
+import { tokenService } from '@/services/api/token-service'
+import { useAuthStore } from '@/store/auth'
+
+export default function useAuth() {
+ const store = useAuthStore()
+ const { user, role, isAuthenticated } = storeToRefs(store)
+
+ const applySession = (payload = {}) => {
+ if (payload.token) tokenService.saveToken(payload.token)
+ if (payload.refreshToken) tokenService.saveRefreshToken(payload.refreshToken)
+ if (payload.user) store.setUser(payload.user)
+ }
+
+ const savePhoneNumber = (phoneNumber) => {
+ if (!phoneNumber) return
+ const current = tokenService.getUserInfo() || {}
+ if (!current.phoneNumber) {
+ store.setUser({ ...current, phoneNumber })
+ }
+ }
+
+ const clearSession = () => {
+ store.clearUser()
+ }
+
+ return {
+ user,
+ role,
+ isAuthenticated,
+ applySession,
+ savePhoneNumber,
+ clearSession,
+ }
+}
diff --git a/src/composables/useDebounce.js b/src/composables/useDebounce.js
new file mode 100644
index 0000000..ed07fb2
--- /dev/null
+++ b/src/composables/useDebounce.js
@@ -0,0 +1,10 @@
+export default function useDebounce(callback, delay = 300) {
+ let timeout
+
+ const debounced = (...args) => {
+ if (timeout) clearTimeout(timeout)
+ timeout = setTimeout(() => callback(...args), delay)
+ }
+
+ return debounced
+}
diff --git a/src/composables/useModal.js b/src/composables/useModal.js
new file mode 100644
index 0000000..4b8bb0c
--- /dev/null
+++ b/src/composables/useModal.js
@@ -0,0 +1,6 @@
+import { useModalStore } from '@/store/modal'
+
+export default function useModal() {
+ const { openModal, closeModal, isModal, getModal } = useModalStore()
+ return { openModal, closeModal, isModal, getModal }
+}
diff --git a/src/composables/usePagination.js b/src/composables/usePagination.js
new file mode 100644
index 0000000..c3ceee0
--- /dev/null
+++ b/src/composables/usePagination.js
@@ -0,0 +1,25 @@
+import { ref } from 'vue'
+
+export const usePagination = (defaultPagination) => {
+ const mergedDefault = { page: 1, perPage: 10, ...defaultPagination }
+ const pagination = ref({ ...mergedDefault })
+
+ const setPagination = (newPagination) => {
+ pagination.value = { ...pagination.value, ...newPagination }
+ }
+
+ const setPage = (page) => setPagination({ page })
+
+ const reset = () => {
+ pagination.value = { ...mergedDefault }
+ }
+
+ return {
+ pagination,
+ setPagination,
+ setPage,
+ reset,
+ }
+}
+
+export default usePagination
diff --git a/src/composables/useYup.js b/src/composables/useYup.js
new file mode 100644
index 0000000..3a482a4
--- /dev/null
+++ b/src/composables/useYup.js
@@ -0,0 +1,73 @@
+import { ref } from 'vue'
+
+export default function useYup(validationSchema) {
+ const errors = ref({})
+
+ const validate = async (values, options) => {
+ const mergeOptions = { abortEarly: false, stripUnknown: true, ...options }
+ try {
+ const response = await validationSchema.validate(values, mergeOptions)
+ if (!(response instanceof Error)) {
+ errors.value = {}
+ return { isValid: true, payload: response }
+ }
+ return { isValid: false, payload: response }
+ } catch (error) {
+ if (error.inner) {
+ const newErrors = {}
+ error.inner.forEach((validationError) => {
+ newErrors[validationError.path] = validationError.message
+ })
+ errors.value = newErrors
+ return { isValid: false }
+ }
+ return { isValid: false, payload: error }
+ }
+ }
+
+ const validateAt = async (field, value) => {
+ try {
+ const pathParts = field.split('.')
+ const lastPart = pathParts.pop()
+ let schemaContext = validationSchema
+ let context = {}
+ if (pathParts.length > 0) {
+ pathParts.forEach((part) => {
+ if (part.includes('[')) {
+ const [arrayPart, indexPart] = part.split(/[[\]]/).filter(Boolean)
+ schemaContext = schemaContext.fields[arrayPart].innerType
+ context = { ...context, [arrayPart]: (context[arrayPart] || [])[indexPart] || {} }
+ } else {
+ context[part] = context[part] || {}
+ schemaContext = schemaContext.fields[part]
+ }
+ })
+
+ context[lastPart] = value
+ await schemaContext.validateAt(lastPart, context)
+ errors.value[field] = null
+ } else {
+ await validationSchema.validateAt(field, { [field]: value })
+ errors.value[field] = null
+ }
+ } catch (error) {
+ errors.value[field] = error.message
+ }
+ }
+
+ const resetErrors = () => {
+ errors.value = {}
+ }
+
+ const setError = (field, error) => {
+ errors.value[field] = error
+ }
+
+ return {
+ validate,
+ validateAt,
+ errors,
+ resetErrors,
+ setError,
+ }
+}
diff --git a/src/constants/fields.js b/src/constants/fields.js
new file mode 100644
index 0000000..b7cdd14
--- /dev/null
+++ b/src/constants/fields.js
@@ -0,0 +1,93 @@
+export const fields = {
+ mobile: 'شماره موبایل',
+ phoneNumber: 'شماره موبایل',
+ phone: 'تلفن ثابت',
+ password: 'رمز عبور',
+ passwordConfirmation: 'تکرار رمز عبور',
+ newPassword: 'رمز عبور جدید',
+ currentPassword: 'رمز عبور فعلی',
+ email: 'ایمیل',
+ code: 'کد تایید',
+
+ name: 'نام',
+ fullName: 'نام و نام خانوادگی',
+ firstName: 'نام',
+ lastName: 'نام خانوادگی',
+ nationalCode: 'کد ملی',
+ postalCode: 'کد پستی',
+
+ birthDate: 'تاریخ تولد',
+ gender: 'جنسیت',
+ maritalStatus: 'وضعیت تأهل',
+
+ province: 'استان',
+ provinceId: 'استان',
+ city: 'شهر',
+ cityId: 'شهر',
+ address: 'آدرس',
+
+ title: 'عنوان',
+ description: 'توضیحات',
+ bio: 'بیوگرافی',
+ message: 'پیام',
+ content: 'محتوا',
+ rejectionReason: 'دلیل رد',
+ adminNote: 'یادداشت مدیر',
+ activitySummary: 'خلاصهٔ فعالیت',
+
+ avatar: 'تصویر پروفایل',
+ image: 'تصویر',
+
+ status: 'وضعیت',
+ role: 'نقش',
+ roleId: 'نقش',
+ isActive: 'فعال',
+ isActiveByDefault: 'فعال بهصورت پیشفرض',
+ randomize: 'تصادفی',
+
+ startDate: 'تاریخ شروع',
+ endDate: 'تاریخ پایان',
+ fromDate: 'از تاریخ',
+ toDate: 'تا تاریخ',
+
+ capacity: 'ظرفیت',
+ minCapacity: 'حداقل ظرفیت',
+ maxCapacity: 'حداکثر ظرفیت',
+ defaultCapacity: 'ظرفیت پیشفرض',
+
+ order: 'ترتیب',
+ priority: 'اولویت',
+ durationMinutes: 'مدت زمان (دقیقه)',
+ passingScore: 'حد نصاب قبولی',
+ minSessions: 'حداقل جلسات',
+ minQuizzes: 'حداقل آزمونها',
+ minAssignments: 'حداقل تکالیف',
+
+ termId: 'ترم',
+ templateId: 'قالب',
+ courseId: 'دوره',
+ courseTemplateId: 'قالب دوره',
+ sessionId: 'جلسه',
+ sessionType: 'نوع جلسه',
+ teacherId: 'مدرس',
+ defaultTeacherId: 'مدرس پیشفرض',
+ studentIds: 'دانشآموزان',
+
+ educationStatus: 'وضعیت تحصیلی',
+ fieldOfStudy: 'رشتهٔ تحصیلی',
+ seminaryLevel: 'مقطع حوزه',
+ hijabApproach: 'رویکرد حجاب',
+
+ prerequisites: 'پیشنیازها',
+ specializedTopics: 'موضوعات تخصصی',
+ propagationPlatforms: 'بسترهای تبلیغ',
+ propagationMethodDescription: 'شرح روش تبلیغ',
+ propagationExperienceYears: 'سنوات تجربهٔ تبلیغ',
+ relevantCertificates: 'گواهینامههای مرتبط',
+
+ onlinePlatformDetails: 'جزئیات بستر آنلاین',
+ otherPlatformDetails: 'جزئیات سایر بسترها',
+
+ faithProductionAudio: 'صدای تولید ایمانی',
+ leaderMessageVideo: 'ویدیوی پیام رهبر',
+}
diff --git a/src/constants/rules/nationalCodeRule.js b/src/constants/rules/nationalCodeRule.js
new file mode 100644
index 0000000..ceedd66
--- /dev/null
+++ b/src/constants/rules/nationalCodeRule.js
@@ -0,0 +1,20 @@
+import { string } from 'yup'
+
+import { fields } from '@/constants/fields'
+import { convertToEnNumber } from '@/utils/convert-check-digits'
+
+export const nationalCodeRule = string()
+ .required()
+ .test(
+ 'national-code',
+ ({ path }) => `${fields[path] || path} نامعتبر است`,
+ (value) => {
+ const v = convertToEnNumber(value || '')
+ if (!v || v.length !== 10 || !/^\d{10}$/.test(v)) return false
+ const check = +v[9]
+ let sum = 0
+ for (let i = 0; i < 9; i += 1) sum += +v[i] * (10 - i)
+ sum %= 11
+ return (sum < 2 && check === sum) || (sum >= 2 && check === 11 - sum)
+ }
+ )
diff --git a/src/constants/rules/passwordConfirmationRule.js b/src/constants/rules/passwordConfirmationRule.js
new file mode 100644
index 0000000..34ece6a
--- /dev/null
+++ b/src/constants/rules/passwordConfirmationRule.js
@@ -0,0 +1,14 @@
+import { ref, string } from 'yup'
+
+export const passwordConfirmationRule = string()
+ .required()
+ .oneOf([ref('password')], 'تکرار رمزعبور با رمزعبور یکسان نیست')
+
+export const optionalPasswordConfirmationRule = string()
+ .nullable()
+ .notRequired()
+ .test('match', 'تکرار رمزعبور با رمزعبور یکسان نیست', function (value) {
+ const pw = this.parent.password
+ if (!pw && !value) return true
+ return value === pw
+ })
diff --git a/src/constants/rules/passwordRule.js b/src/constants/rules/passwordRule.js
new file mode 100644
index 0000000..726c706
--- /dev/null
+++ b/src/constants/rules/passwordRule.js
@@ -0,0 +1,16 @@
+import { string } from 'yup'
+
+export const passwordRule = string()
+ .required()
+ .min(8, 'رمزعبور باید حداقل ۸ کاراکتر باشد')
+ .matches(/\d/, 'رمزعبور باید شامل حداقل یک عدد باشد')
+ .matches(/[a-z]/, 'رمزعبور باید شامل حداقل یک حرف کوچک باشد')
+ .matches(/[A-Z]/, 'رمزعبور باید شامل حداقل یک حرف بزرگ باشد')
+
+export const optionalPasswordRule = string()
+ .nullable()
+ .notRequired()
+ .test('strong-password', 'رمزعبور باید معتبر باشد', (value) => {
+ if (!value) return true
+ return passwordRule.isValidSync(value)
+ })
diff --git a/src/constants/rules/phoneNumberRule.js b/src/constants/rules/phoneNumberRule.js
new file mode 100644
index 0000000..e967867
--- /dev/null
+++ b/src/constants/rules/phoneNumberRule.js
@@ -0,0 +1,7 @@
+import { string } from 'yup'
+
+import { fields } from '@/constants/fields'
+
+export const phoneNumberRule = string()
+ .required()
+ .matches(/^09\d{9}$/, ({ path }) => `${fields[path] || path} نامعتبر است`)
diff --git a/src/enums/index.js b/src/enums/index.js
new file mode 100644
index 0000000..647eb95
--- /dev/null
+++ b/src/enums/index.js
@@ -0,0 +1,195 @@
+export const getEnumObject = (enumArray, key = 'value', value = 'label') =>
+ enumArray.reduce((acc, option) => {
+ acc[option[key]] = option[value]
+ return acc
+ }, {})
+
+export const ROLES = Object.freeze([
+ { value: 'admin', label: 'مدیر' },
+ { value: 'student', label: 'دانشآموز' },
+])
+
+export const LOGIN_STEPS = Object.freeze({
+ LOGIN: 1,
+ LOGIN_WITH_VERIFY_CODE: 2,
+ VERIFY_CODE: 3,
+})
+
+export const SIGNUP_STEPS = Object.freeze({
+ SIGNUP: 1,
+ VERIFY_CODE: 2,
+})
+
+export const STUDENT_REGISTRATION = Object.freeze({
+ PERSONAL_INFORMATION: 1,
+ EDUCATIONAL_INFORMATION: 2,
+ PROFESSIONAL_INFORMATION: 3,
+ SKILL_ASSESSMENT_PART_1: 4,
+ SKILL_ASSESSMENT_PART_2: 5,
+ SKILL_ASSESSMENT_PART_3: 6,
+ SKILL_ASSESSMENT_PART_4: 7,
+ SKILL_ASSESSMENT_PART_5: 8,
+ SKILL_ASSESSMENT_PART_6: 9,
+ SKILL_ASSESSMENT_PART_7: 10,
+})
+
+export const STUDENT_REGISTRATION_ORDER = Object.freeze(Object.values(STUDENT_REGISTRATION))
+
+export const USER_STATUS = Object.freeze({
+ approved: 'تأیید شده',
+ pending: 'در انتظار',
+ rejected: 'رد شده',
+ blocked: 'مسدود',
+})
+
+export const MARITAL_STATUS = Object.freeze({
+ single: 'مجرد',
+ married: 'متاهل',
+ divorced: 'مطلقه',
+ widowed: 'بیوه',
+})
+
+export const GENDER = Object.freeze({
+ male: 'اقا',
+ female: 'خانم',
+})
+
+export const ROLE_LABELS = Object.freeze({
+ admin: 'مدیر',
+ counselor: 'مشاور',
+ missionary: 'مبلغ',
+ student: 'دانشجو',
+ teacher: 'استاد',
+})
+
+export const CHANGEABLE_ROLES = Object.freeze(['student', 'teacher', 'missionary', 'counselor'])
+
+export const EDUCATION_STATUS = Object.freeze({
+ seminary_student: 'طلبه',
+ seminary_and_university_student: 'طلبه و دانشجو',
+ graduate: 'فارغ التحصیلی',
+})
+
+export const SEMINARY_LEVEL = Object.freeze({
+ level_2: 'سطح دو',
+ level_3: 'سطح سه',
+ level_4: 'سطح چهار',
+ not_applicable: 'طلبه نیستم',
+})
+
+export const UNIVERSITY_LEVEL = Object.freeze({
+ bachelor: ' مقطع کارشناسی (لیسانس)',
+ master: ' مقطع کارشناسی ارشد (فوق لیسانس)',
+ phd: ' مقطع دکتری',
+ not_applicable: 'دانشجو نیستم',
+})
+
+export const PROPAGATION_PLATFORM = Object.freeze({
+ home_gathering_occasional: 'روضههای خانگی مناسبتی',
+ home_gathering_regular: 'جلسات خانگی ثابت',
+ online: 'فضای مجازی',
+ university: 'دانشگاه',
+ school: 'مدرسه',
+ other: 'سایر فضاهای تبلیغی',
+ none: 'فعالیتی نداشتهام',
+})
+
+export const LOW_SATISFACTION_RESPONSE = Object.freeze({
+ change_the_method: 'روش را عوض میکنید در حالی که ایمان به صحت آن دارید',
+ insist_on_your_method:
+ 'اصرار بر روش و مسیر خود دارید و معتقد هستید مخاطب باید خود را به آن سطح برساند',
+ other: 'کاری به غیر از گزینههای ذکر شده انجام میدهید',
+})
+
+export const SESSION_CANCELLATION_RESPONSE = Object.freeze({
+ teach_how_to_reduce_costs: 'آموزش روشهای کاهش هزینه به صاحب بیت',
+ provide_solutions_to_cover_meeting_costs: 'ارائه راهکارهای تامین هزینههای جلسه',
+ setup_or_find_an_alternative_meeting: 'راهاندازی یا پیدا کردن یک جلسه جایگزین با همان جمع',
+ convince_the_homeowner_to_continue: 'توجیه و اقناع صاحب بیت برای ادامه دادن',
+ other: 'کاری به غیر از گزینههای ذکر شده انجام میدهید',
+})
+
+export const AUDIENCE_CONFLICT_RESPONSE = Object.freeze({
+ divide_the_crowd:
+ 'جمع را تفکیک میکنید و برای هر کدام متناسب با آن چیزی که میخواهند ارائه میدهید',
+ convince_one_of_the_groups: 'سعی میکنید یکی از گروهها را متقاعد کنید',
+ considering_one_of_the_groups: 'بیتوجه به یکی از گروهها به ارائه خود میپردازید',
+ other: 'کاری غیر از گزینههای ذکر شده را انجام میدهید',
+})
+
+export const COMPETING_PROPAGATOR_RESPONSE = Object.freeze({
+ strengthen_yourself: 'خود را در زمینه ابزارها و روشها تقویت میکنید تا جلسه شما پررونق شود',
+ close_your_meeting_and_strengthen_the_preacher:
+ 'جلسه خود را تعطیل کرده و سعی در تقویت بنیه معرفتی مبلغه جلسه مذکور خواهید داشت',
+ convince_the_other_preacher_to_strengthen_or_close:
+ 'سعی میکنید مبلغه دیگر را توجیه و اقناع کنید تا یا بنیه خود را تقویت کند یا جلسه را تعطیل کند',
+ bring_a_skilled_person_with_me:
+ 'یک نفر دارای مهارت را به عنوان کمک و معین برای تقویت جلسه و روش و ابزارها، با خود همراه میکردم',
+ other: 'کاری غیر از گزینههای ذکر شده انجام میدادم',
+})
+
+export const VERIFICATION_MEDIA_TYPE = Object.freeze({
+ FAITH_PRODUCTION: 'faith_production',
+ LEADER_MESSAGE: 'leader_message',
+})
+
+export const SESSION_TYPE = Object.freeze({
+ in_person: 'حضوری',
+ online: 'آنلاین',
+ video: 'ویدئو',
+ audio: 'صوتی',
+ text: 'متن',
+ slide: 'اسلاید',
+ pdf: 'PDF',
+})
+
+export const SESSION_PLATFORM = Object.freeze({
+ zoom: 'Zoom',
+ google_meet: 'Google Meet',
+ teams: 'Microsoft Teams',
+ custom: 'سایر',
+})
+
+export const ASSIGNMENT_PRIORITY = Object.freeze({
+ mandatory: 'اجباری',
+ optional: 'اختیاری',
+})
+
+export const TICKET_STATUS = Object.freeze({
+ pending: 'در انتظار پاسخ',
+ answered: 'پاسخ داده شده',
+ closed: 'بسته شده',
+})
+
+export const STUDENT_COURSE_STATUS = Object.freeze({
+ watching: 'در حال گذراندن',
+ waitForExam: 'در انتظار آزمون',
+ completed: 'تکمیل شده',
+ failed: 'عدم قبولی',
+})
+
+export const PRIORITY_STATUS = Object.freeze({
+ high: 'بالا',
+ medium: 'متوسط',
+ low: 'پایین',
+})
+
+export const SERVICE_STATUS = Object.freeze({
+ approved: 'تایید شده',
+ pending: 'در انتظار بررسی',
+ in_progress: 'در حال انجام',
+ completed: 'تکمیل شده',
+})
+
+export const SERVICE_TYPE = Object.freeze({
+ loan: 'وام',
+ consultation: 'مشاوره',
+ educational: 'آموزشی',
+ other: 'سایر',
+})
+
+export const CONSULTATION_STATUS = Object.freeze({
+ in_progress: 'در حال گفتگو',
+ answered: 'پاسخ داده شده',
+ closed: 'بسته شده',
+})
diff --git a/src/features/admin/assignments/components/AssignmentItem.vue b/src/features/admin/assignments/components/AssignmentItem.vue
new file mode 100644
index 0000000..b4ea9dc
--- /dev/null
+++ b/src/features/admin/assignments/components/AssignmentItem.vue
@@ -0,0 +1,204 @@
+
+
+
+
{{ assignment.title || '—' }}
+
+ دوره:
+
+ {{ assignment.courseTemplate?.title || assignment.courseTemplateTitle || '—' }}
+
+ |
+ جلسه:
+
+ {{ assignment.session?.title || assignment.sessionTitle || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/components/AssignmentsFilters.vue b/src/features/admin/assignments/components/AssignmentsFilters.vue
new file mode 100644
index 0000000..b1e5b17
--- /dev/null
+++ b/src/features/admin/assignments/components/AssignmentsFilters.vue
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/components/modals/AddAssignmentModal.vue b/src/features/admin/assignments/components/modals/AddAssignmentModal.vue
new file mode 100644
index 0000000..e1a3a74
--- /dev/null
+++ b/src/features/admin/assignments/components/modals/AddAssignmentModal.vue
@@ -0,0 +1,325 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/components/modals/AssignmentDetailsModal.vue b/src/features/admin/assignments/components/modals/AssignmentDetailsModal.vue
new file mode 100644
index 0000000..2829300
--- /dev/null
+++ b/src/features/admin/assignments/components/modals/AssignmentDetailsModal.vue
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
{{ assignment.title || '—' }}
+
+
+ دوره:
+ {{ assignment.courseTemplate?.title || assignment.courseTemplateTitle || '—' }}
+
+ |
+ جلسه: {{ assignment.session?.title || assignment.sessionTitle || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/components/modals/AssignmentSubmissionDetailsModal.vue b/src/features/admin/assignments/components/modals/AssignmentSubmissionDetailsModal.vue
new file mode 100644
index 0000000..512d7d0
--- /dev/null
+++ b/src/features/admin/assignments/components/modals/AssignmentSubmissionDetailsModal.vue
@@ -0,0 +1,350 @@
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ assignmentTitle }}
+
+ ترم: {{ submission.termTitle || '—' }}
+ |
+ دوره: {{ submission.courseTemplateTitle || '—' }}
+ |
+ جلسه: {{ submission.sessionTitle || '—' }}
+ |
+ تاریخ: {{ submittedAt }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/components/modals/AssignmentSubmissionsModal.vue b/src/features/admin/assignments/components/modals/AssignmentSubmissionsModal.vue
new file mode 100644
index 0000000..446ed09
--- /dev/null
+++ b/src/features/admin/assignments/components/modals/AssignmentSubmissionsModal.vue
@@ -0,0 +1,237 @@
+
+
+
+
+
+
{{ data.title }}
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName(submission.user) }}
+
+ {{ locationFromAddress(submission.user) || '—' }}
+
+
+
+
+
+ تاریخ ارسال:
+ {{ submittedAt(submission) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/pages/AssignmentsListPage.vue b/src/features/admin/assignments/pages/AssignmentsListPage.vue
new file mode 100644
index 0000000..8fef578
--- /dev/null
+++ b/src/features/admin/assignments/pages/AssignmentsListPage.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/assignments/schema/index.js b/src/features/admin/assignments/schema/index.js
new file mode 100644
index 0000000..7fb4b00
--- /dev/null
+++ b/src/features/admin/assignments/schema/index.js
@@ -0,0 +1,17 @@
+import { number, object, string } from 'yup'
+
+export const assignmentSchema = object().shape({
+ title: string().required().min(3),
+ courseTemplateId: string().required(),
+ sessionId: string().required(),
+ startDate: string().required(),
+ endDate: string().required(),
+ priority: string().required(),
+ description: string().nullable().notRequired(),
+})
+
+export const assignmentSubmissionReviewSchema = object().shape({
+ score: number().typeError('نمره باید عدد باشد').required(),
+ status: string().required(),
+ reviewerNote: string().nullable().notRequired(),
+})
diff --git a/src/features/admin/consultations/components/ConsultationItem.vue b/src/features/admin/consultations/components/ConsultationItem.vue
new file mode 100644
index 0000000..685ff15
--- /dev/null
+++ b/src/features/admin/consultations/components/ConsultationItem.vue
@@ -0,0 +1,285 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName }}
+
+ شماره درخواست :
+
+ {{ consultation.requestId || consultation.id || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/consultations/components/ConsultationsFilters.vue b/src/features/admin/consultations/components/ConsultationsFilters.vue
new file mode 100644
index 0000000..31ab2fe
--- /dev/null
+++ b/src/features/admin/consultations/components/ConsultationsFilters.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/consultations/components/modals/ConsultationDetailsModal.vue b/src/features/admin/consultations/components/modals/ConsultationDetailsModal.vue
new file mode 100644
index 0000000..0c4751e
--- /dev/null
+++ b/src/features/admin/consultations/components/modals/ConsultationDetailsModal.vue
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+ {{ consultationDate }}
+
+
+
+
+
+
+
{{ message.text }}
+
{{ messageTime(message) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/consultations/pages/ConsultationsListPage.vue b/src/features/admin/consultations/pages/ConsultationsListPage.vue
new file mode 100644
index 0000000..4b0e106
--- /dev/null
+++ b/src/features/admin/consultations/pages/ConsultationsListPage.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/CourseItem.vue b/src/features/admin/courses/components/CourseItem.vue
new file mode 100644
index 0000000..2341933
--- /dev/null
+++ b/src/features/admin/courses/components/CourseItem.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
+ دوره
+ {{ course.title }}
+
+
+
+ استاد:
+ {{ teacherName }}
+
+
+
+
+
+
+
+
+
+ غیرفعال
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/CourseSessionItem.vue b/src/features/admin/courses/components/CourseSessionItem.vue
new file mode 100644
index 0000000..d403924
--- /dev/null
+++ b/src/features/admin/courses/components/CourseSessionItem.vue
@@ -0,0 +1,185 @@
+
+
+
+
+ {{ orderLabel }}
+ –
+ {{ session.title }}
+
+
+
+ زمان جلسه:
+ {{ durationLabel }}
+
+
+
+
+
+
+ {{ badge.label }}
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/CoursesFilters.vue b/src/features/admin/courses/components/CoursesFilters.vue
new file mode 100644
index 0000000..b0a3aa8
--- /dev/null
+++ b/src/features/admin/courses/components/CoursesFilters.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/modals/AddCourseStudentModal.vue b/src/features/admin/courses/components/modals/AddCourseStudentModal.vue
new file mode 100644
index 0000000..2839638
--- /dev/null
+++ b/src/features/admin/courses/components/modals/AddCourseStudentModal.vue
@@ -0,0 +1,307 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userLabel(user) }}
+
+ {{ user.address?.province?.name || '—' }}
+ ،
+ {{ user.address?.city?.name || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/modals/AddOfferedCourseModal.vue b/src/features/admin/courses/components/modals/AddOfferedCourseModal.vue
new file mode 100644
index 0000000..fd489b2
--- /dev/null
+++ b/src/features/admin/courses/components/modals/AddOfferedCourseModal.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/modals/AddSessionToCourseModal.vue b/src/features/admin/courses/components/modals/AddSessionToCourseModal.vue
new file mode 100644
index 0000000..2fa86ac
--- /dev/null
+++ b/src/features/admin/courses/components/modals/AddSessionToCourseModal.vue
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+ {{ session.title || `جلسه ${session.order || ''}` }}
+
+
+
+ استاد:
+ {{ teacherName(session) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/components/modals/CourseDetailsModal.vue b/src/features/admin/courses/components/modals/CourseDetailsModal.vue
new file mode 100644
index 0000000..1b001b6
--- /dev/null
+++ b/src/features/admin/courses/components/modals/CourseDetailsModal.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ studentName(student) }}
+
+ {{ student.address?.province?.name || '—' }}
+ ،
+ {{ student.address?.city?.name || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/pages/CourseTemplateFormPage.vue b/src/features/admin/courses/pages/CourseTemplateFormPage.vue
new file mode 100644
index 0000000..d7dcf01
--- /dev/null
+++ b/src/features/admin/courses/pages/CourseTemplateFormPage.vue
@@ -0,0 +1,372 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/pages/CoursesListPage.vue b/src/features/admin/courses/pages/CoursesListPage.vue
new file mode 100644
index 0000000..0c30fdc
--- /dev/null
+++ b/src/features/admin/courses/pages/CoursesListPage.vue
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/courses/schema/index.js b/src/features/admin/courses/schema/index.js
new file mode 100644
index 0000000..b13f470
--- /dev/null
+++ b/src/features/admin/courses/schema/index.js
@@ -0,0 +1,18 @@
+import { array, boolean, object, string } from 'yup'
+
+export const courseTemplateSchema = object().shape({
+ title: string().required().min(3).max(255),
+ defaultTeacherId: string().required(),
+ defaultCapacity: string().required(),
+ prerequisites: array().nullable().default([]),
+ description: string().nullable().notRequired(),
+})
+
+export const offeredCourseSchema = object().shape({
+ termId: string().required(),
+ templateId: string().required(),
+ title: string().required(),
+ capacity: string().required(),
+ imageId: string().nullable().notRequired(),
+ isActive: boolean().nullable().notRequired(),
+})
diff --git a/src/features/admin/exams/components/ExamItem.vue b/src/features/admin/exams/components/ExamItem.vue
new file mode 100644
index 0000000..bed85f0
--- /dev/null
+++ b/src/features/admin/exams/components/ExamItem.vue
@@ -0,0 +1,204 @@
+
+
+
+
{{ exam.title || '—' }}
+
+ دوره:
+
+ {{ exam.courseTemplate?.title || exam.courseTemplateTitle || '—' }}
+
+ |
+ جلسه:
+
+ {{ exam.session?.title || exam.sessionTitle || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/components/ExamQuestionBuilder.vue b/src/features/admin/exams/components/ExamQuestionBuilder.vue
new file mode 100644
index 0000000..ece8760
--- /dev/null
+++ b/src/features/admin/exams/components/ExamQuestionBuilder.vue
@@ -0,0 +1,406 @@
+
+
+
+
+
سوال شماره {{ questionIndex + 1 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ updateQuestion(question.id, { correctAnswerId: value || null })
+ "
+ />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/components/ExamsFilters.vue b/src/features/admin/exams/components/ExamsFilters.vue
new file mode 100644
index 0000000..fa905c6
--- /dev/null
+++ b/src/features/admin/exams/components/ExamsFilters.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/components/modals/ExamDetailsModal.vue b/src/features/admin/exams/components/modals/ExamDetailsModal.vue
new file mode 100644
index 0000000..7174c8e
--- /dev/null
+++ b/src/features/admin/exams/components/modals/ExamDetailsModal.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
{{ exam.title || '—' }}
+
+ دوره: {{ exam.courseTemplate?.title || exam.courseTemplateTitle || '—' }}
+ |
+ جلسه: {{ exam.session?.title || exam.sessionTitle || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}.
+ {{ q.title }}
+
+ ({{ q.score }} نمره)
+
+
+
+ -
+ {{ optionLabel(ai) }}:
+ {{ a.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/components/modals/ExamParticipantDetailsModal.vue b/src/features/admin/exams/components/modals/ExamParticipantDetailsModal.vue
new file mode 100644
index 0000000..9f91538
--- /dev/null
+++ b/src/features/admin/exams/components/modals/ExamParticipantDetailsModal.vue
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+ {{ participantName }}
+
+
+
+
+
+
+
+
+
+
+ {{ qIdx + 1 }}- {{ question.title }}
+
+
+
+ {{ aIdx + 1 }}.
+ {{ answer.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/components/modals/ExamParticipantsModal.vue b/src/features/admin/exams/components/modals/ExamParticipantsModal.vue
new file mode 100644
index 0000000..e14bbb8
--- /dev/null
+++ b/src/features/admin/exams/components/modals/ExamParticipantsModal.vue
@@ -0,0 +1,233 @@
+
+
+
+
+
+
{{ data.title }}
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName(participant) }}
+
+ {{ participant.location || locationFromAddress(participant) || '—' }}
+
+
+
+
+
+ تاریخ شرکت:
+ {{ registeredAt(participant) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/pages/ExamFormPage.vue b/src/features/admin/exams/pages/ExamFormPage.vue
new file mode 100644
index 0000000..5ec436e
--- /dev/null
+++ b/src/features/admin/exams/pages/ExamFormPage.vue
@@ -0,0 +1,347 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/pages/ExamsListPage.vue b/src/features/admin/exams/pages/ExamsListPage.vue
new file mode 100644
index 0000000..ded1cf4
--- /dev/null
+++ b/src/features/admin/exams/pages/ExamsListPage.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/exams/schema/index.js b/src/features/admin/exams/schema/index.js
new file mode 100644
index 0000000..f3ea66a
--- /dev/null
+++ b/src/features/admin/exams/schema/index.js
@@ -0,0 +1,10 @@
+import { number, object, string } from 'yup'
+
+export const examSchema = object().shape({
+ title: string().required().min(3),
+ sessionId: string().required(),
+ endDate: string().required(),
+ durationMinutes: number().typeError('مدت زمان باید عدد باشد').required(),
+ passingScore: number().typeError('حد نصاب قبولی باید عدد باشد').required(),
+ description: string().nullable().notRequired(),
+})
diff --git a/src/features/admin/messages/components/TicketItem.vue b/src/features/admin/messages/components/TicketItem.vue
new file mode 100644
index 0000000..8672df2
--- /dev/null
+++ b/src/features/admin/messages/components/TicketItem.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName }}
+
{{ ticket.title || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/messages/components/TicketsFilters.vue b/src/features/admin/messages/components/TicketsFilters.vue
new file mode 100644
index 0000000..fec4ada
--- /dev/null
+++ b/src/features/admin/messages/components/TicketsFilters.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/messages/components/modals/TicketDetailsModal.vue b/src/features/admin/messages/components/modals/TicketDetailsModal.vue
new file mode 100644
index 0000000..04e624d
--- /dev/null
+++ b/src/features/admin/messages/components/modals/TicketDetailsModal.vue
@@ -0,0 +1,512 @@
+
+
+
+
+
+
+
+ {{ ticketDate }}
+
+
+
+
+
+
+
{{ message.text }}
+
{{ messageTime(message) }}
+
+
+
+
+
+
+
+
+
+ {{ attachment.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/messages/pages/TicketsListPage.vue b/src/features/admin/messages/pages/TicketsListPage.vue
new file mode 100644
index 0000000..a730e19
--- /dev/null
+++ b/src/features/admin/messages/pages/TicketsListPage.vue
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/pages/AdminDashboardPage.vue b/src/features/admin/pages/AdminDashboardPage.vue
new file mode 100644
index 0000000..7506380
--- /dev/null
+++ b/src/features/admin/pages/AdminDashboardPage.vue
@@ -0,0 +1,53 @@
+
+
+
+ پنل مدیریت
+ آخرین اطلاعات موسسه شما
+
+
+
این بخش در مراحل بعدی توسعه مییابد.
+
+
+
+
+
+
diff --git a/src/features/admin/router.js b/src/features/admin/router.js
new file mode 100644
index 0000000..2ac1305
--- /dev/null
+++ b/src/features/admin/router.js
@@ -0,0 +1,128 @@
+export default [
+ {
+ path: '/main-dashboard',
+ name: 'admin-dashboard',
+ component: () => import('@/features/admin/pages/AdminDashboardPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'پیشخوان' },
+ },
+ {
+ path: '/users',
+ name: 'admin-users',
+ component: () => import('@/features/admin/users/pages/UsersListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت کاربران' },
+ },
+ {
+ path: '/add-user',
+ name: 'admin-add-user',
+ component: () => import('@/features/admin/users/pages/UserFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'افزودن کاربر جدید' },
+ },
+ {
+ path: '/edit-user/:id',
+ name: 'admin-edit-user',
+ component: () => import('@/features/admin/users/pages/UserFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'ویرایش کاربر' },
+ },
+ {
+ path: '/user-verification',
+ name: 'admin-user-verification',
+ component: () => import('@/features/admin/users/pages/UserVerificationPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'تایید هویت کاربران' },
+ },
+ {
+ path: '/terms',
+ name: 'admin-terms',
+ component: () => import('@/features/admin/terms/pages/TermsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت ترم' },
+ },
+ {
+ path: '/add-term',
+ name: 'admin-add-term',
+ component: () => import('@/features/admin/terms/pages/TermFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'افزودن ترم جدید' },
+ },
+ {
+ path: '/edit-term/:id',
+ name: 'admin-edit-term',
+ component: () => import('@/features/admin/terms/pages/TermFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'ویرایش ترم' },
+ },
+ {
+ path: '/courses',
+ name: 'admin-courses',
+ component: () => import('@/features/admin/courses/pages/CoursesListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت دوره' },
+ },
+ {
+ path: '/add-course-template',
+ name: 'admin-add-course-template',
+ component: () => import('@/features/admin/courses/pages/CourseTemplateFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'افزودن دوره الگو' },
+ },
+ {
+ path: '/edit-course-template/:id',
+ name: 'admin-edit-course-template',
+ component: () => import('@/features/admin/courses/pages/CourseTemplateFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'ویرایش دوره الگو' },
+ },
+ {
+ path: '/sessions',
+ name: 'admin-sessions',
+ component: () => import('@/features/admin/sessions/pages/SessionsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت جلسات' },
+ },
+ {
+ path: '/add-session',
+ name: 'admin-add-session',
+ component: () => import('@/features/admin/sessions/pages/SessionFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'افزودن جلسه جدید' },
+ },
+ {
+ path: '/edit-session/:id',
+ name: 'admin-edit-session',
+ component: () => import('@/features/admin/sessions/pages/SessionFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'ویرایش جلسه' },
+ },
+ {
+ path: '/exams',
+ name: 'admin-exams',
+ component: () => import('@/features/admin/exams/pages/ExamsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت آزمونها' },
+ },
+ {
+ path: '/add-exam',
+ name: 'admin-add-exam',
+ component: () => import('@/features/admin/exams/pages/ExamFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'افزودن آزمون جدید' },
+ },
+ {
+ path: '/edit-exam/:id',
+ name: 'admin-edit-exam',
+ component: () => import('@/features/admin/exams/pages/ExamFormPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'ویرایش آزمون' },
+ },
+ {
+ path: '/assignments',
+ name: 'admin-assignments',
+ component: () => import('@/features/admin/assignments/pages/AssignmentsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت تکالیف' },
+ },
+ {
+ path: '/messages',
+ name: 'admin-messages',
+ component: () => import('@/features/admin/messages/pages/TicketsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت پیامها' },
+ },
+ {
+ path: '/services',
+ name: 'admin-services',
+ component: () => import('@/features/admin/services/pages/ServicesListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت خدمات' },
+ },
+ {
+ path: '/consultations',
+ name: 'admin-consultations',
+ component: () => import('@/features/admin/consultations/pages/ConsultationsListPage.vue'),
+ meta: { layout: 'admin', role: 'admin', title: 'مدیریت مشاوره' },
+ },
+]
diff --git a/src/features/admin/services/components/ServiceItem.vue b/src/features/admin/services/components/ServiceItem.vue
new file mode 100644
index 0000000..3575908
--- /dev/null
+++ b/src/features/admin/services/components/ServiceItem.vue
@@ -0,0 +1,296 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName }}
+
+ شماره درخواست:
+ {{ service.requestId || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/services/components/ServicesFilters.vue b/src/features/admin/services/components/ServicesFilters.vue
new file mode 100644
index 0000000..7ea6613
--- /dev/null
+++ b/src/features/admin/services/components/ServicesFilters.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/services/components/modals/SendMessageModal.vue b/src/features/admin/services/components/modals/SendMessageModal.vue
new file mode 100644
index 0000000..88f71d7
--- /dev/null
+++ b/src/features/admin/services/components/modals/SendMessageModal.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/services/components/modals/ServiceDetailsModal.vue b/src/features/admin/services/components/modals/ServiceDetailsModal.vue
new file mode 100644
index 0000000..f7bc17d
--- /dev/null
+++ b/src/features/admin/services/components/modals/ServiceDetailsModal.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/services/pages/ServicesListPage.vue b/src/features/admin/services/pages/ServicesListPage.vue
new file mode 100644
index 0000000..c2b89f6
--- /dev/null
+++ b/src/features/admin/services/pages/ServicesListPage.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/components/SessionItem.vue b/src/features/admin/sessions/components/SessionItem.vue
new file mode 100644
index 0000000..8629e33
--- /dev/null
+++ b/src/features/admin/sessions/components/SessionItem.vue
@@ -0,0 +1,197 @@
+
+
+
+
+
![]()
+
+
+
+
+
{{ session.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/components/SessionsFilters.vue b/src/features/admin/sessions/components/SessionsFilters.vue
new file mode 100644
index 0000000..d5e0335
--- /dev/null
+++ b/src/features/admin/sessions/components/SessionsFilters.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/components/modals/SessionAttendanceModal.vue b/src/features/admin/sessions/components/modals/SessionAttendanceModal.vue
new file mode 100644
index 0000000..f815756
--- /dev/null
+++ b/src/features/admin/sessions/components/modals/SessionAttendanceModal.vue
@@ -0,0 +1,299 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userName(row.user) }}
+
+ {{ row.user?.address?.province?.name || '—' }}
+ ،
+ {{ row.user?.address?.city?.name || '—' }}
+
+
+
+
+
+ {{ statusLabel(row.status) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/components/modals/SessionDetailsModal.vue b/src/features/admin/sessions/components/modals/SessionDetailsModal.vue
new file mode 100644
index 0000000..3ef6dd8
--- /dev/null
+++ b/src/features/admin/sessions/components/modals/SessionDetailsModal.vue
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
{{ session.title || '—' }}
+
+ دوره: {{ session.courseTemplate.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/pages/SessionFormPage.vue b/src/features/admin/sessions/pages/SessionFormPage.vue
new file mode 100644
index 0000000..87f1c92
--- /dev/null
+++ b/src/features/admin/sessions/pages/SessionFormPage.vue
@@ -0,0 +1,531 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/pages/SessionsListPage.vue b/src/features/admin/sessions/pages/SessionsListPage.vue
new file mode 100644
index 0000000..5bf3682
--- /dev/null
+++ b/src/features/admin/sessions/pages/SessionsListPage.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/sessions/schema/index.js b/src/features/admin/sessions/schema/index.js
new file mode 100644
index 0000000..d7623b1
--- /dev/null
+++ b/src/features/admin/sessions/schema/index.js
@@ -0,0 +1,10 @@
+import { number, object, string } from 'yup'
+
+export const sessionSchema = object().shape({
+ courseTemplateId: string().required(),
+ title: string().required().min(3),
+ sessionType: string().required(),
+ durationMinutes: number().typeError('مدت زمان باید عدد باشد').required(),
+ order: number().typeError('ترتیب باید عدد باشد').nullable().notRequired(),
+ description: string().nullable().notRequired(),
+})
diff --git a/src/features/admin/terms/components/TermItem.vue b/src/features/admin/terms/components/TermItem.vue
new file mode 100644
index 0000000..3afe332
--- /dev/null
+++ b/src/features/admin/terms/components/TermItem.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
![]()
+
+
+
+
+
{{ term.title }}
+
+
+
+
+ تاریخ شروع:
+ {{ startDate || '—' }}
+
+
+ تاریخ پایان:
+ {{ endDate || '—' }}
+
+
+
+
+
+
+ غیرفعال
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/components/TermsFilters.vue b/src/features/admin/terms/components/TermsFilters.vue
new file mode 100644
index 0000000..c31e424
--- /dev/null
+++ b/src/features/admin/terms/components/TermsFilters.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/components/modals/AddTermStudentModal.vue b/src/features/admin/terms/components/modals/AddTermStudentModal.vue
new file mode 100644
index 0000000..964106d
--- /dev/null
+++ b/src/features/admin/terms/components/modals/AddTermStudentModal.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ userLabel(user) }}
+
+ {{ user.address?.province?.name || '—' }}
+ ،
+ {{ user.address?.city?.name || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/components/modals/AttachCourseToTermModal.vue b/src/features/admin/terms/components/modals/AttachCourseToTermModal.vue
new file mode 100644
index 0000000..8451c8a
--- /dev/null
+++ b/src/features/admin/terms/components/modals/AttachCourseToTermModal.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
{{ template.title }}
+
+
+ استاد:
+ {{ teacherName(template) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/components/modals/TermDetailsModal.vue b/src/features/admin/terms/components/modals/TermDetailsModal.vue
new file mode 100644
index 0000000..4b0f084
--- /dev/null
+++ b/src/features/admin/terms/components/modals/TermDetailsModal.vue
@@ -0,0 +1,465 @@
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ studentName(student) }}
+
+ {{ student.address?.province?.name || '—' }}
+ ،
+ {{ student.address?.city?.name || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ data }}
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/pages/TermFormPage.vue b/src/features/admin/terms/pages/TermFormPage.vue
new file mode 100644
index 0000000..2f18b4c
--- /dev/null
+++ b/src/features/admin/terms/pages/TermFormPage.vue
@@ -0,0 +1,298 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/pages/TermsListPage.vue b/src/features/admin/terms/pages/TermsListPage.vue
new file mode 100644
index 0000000..0b46a32
--- /dev/null
+++ b/src/features/admin/terms/pages/TermsListPage.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/terms/schema/index.js b/src/features/admin/terms/schema/index.js
new file mode 100644
index 0000000..41feeef
--- /dev/null
+++ b/src/features/admin/terms/schema/index.js
@@ -0,0 +1,12 @@
+import { array, mixed, object, string } from 'yup'
+
+export const termSchema = object().shape({
+ title: string().required().min(3),
+ startDate: string().required(),
+ endDate: string().required(),
+ description: string().nullable().notRequired(),
+})
+
+export const addTermStudentSchema = object().shape({
+ studentIds: array().of(mixed()).min(1, 'حداقل یک دانشجو را انتخاب کنید').required(),
+})
diff --git a/src/features/admin/users/components/UsersFilters.vue b/src/features/admin/users/components/UsersFilters.vue
new file mode 100644
index 0000000..8bbc2cf
--- /dev/null
+++ b/src/features/admin/users/components/UsersFilters.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/UsersTable.vue b/src/features/admin/users/components/UsersTable.vue
new file mode 100644
index 0000000..36bc118
--- /dev/null
+++ b/src/features/admin/users/components/UsersTable.vue
@@ -0,0 +1,366 @@
+
+
+
+
+
![]()
+
+
+
+
{{ fullName(user) || '—' }}
+
+ {{ user.phoneNumber }}
+ |
+ کد ملی: {{ user.nationalCode }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/modals/UserAssignmentsModal.vue b/src/features/admin/users/components/modals/UserAssignmentsModal.vue
new file mode 100644
index 0000000..9806170
--- /dev/null
+++ b/src/features/admin/users/components/modals/UserAssignmentsModal.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/modals/UserDetailsModal.vue b/src/features/admin/users/components/modals/UserDetailsModal.vue
new file mode 100644
index 0000000..0a2e35a
--- /dev/null
+++ b/src/features/admin/users/components/modals/UserDetailsModal.vue
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+ اطلاعات ثبت نام این دانشجو کامل نیست.
+
+
+
+
+
![]()
+
+
+
+
+
+ {{ user.status === 'blocked' ? 'غیر فعال' : 'فعال' }}
+
+
نام و نام خانوادگی
+
{{ fullName || '—' }}
+
+ نقش:
+ {{ roleText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/modals/UserExamsModal.vue b/src/features/admin/users/components/modals/UserExamsModal.vue
new file mode 100644
index 0000000..a3c49c6
--- /dev/null
+++ b/src/features/admin/users/components/modals/UserExamsModal.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/verifications/VerificationItem.vue b/src/features/admin/users/components/verifications/VerificationItem.vue
new file mode 100644
index 0000000..b2f1674
--- /dev/null
+++ b/src/features/admin/users/components/verifications/VerificationItem.vue
@@ -0,0 +1,252 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
{{ fullName }}
+
+ {{ user.address?.province?.name || '—' }}
+ ،
+ {{ user.address?.city?.name || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/verifications/VerificationsFilters.vue b/src/features/admin/users/components/verifications/VerificationsFilters.vue
new file mode 100644
index 0000000..c715644
--- /dev/null
+++ b/src/features/admin/users/components/verifications/VerificationsFilters.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/verifications/modals/RejectReasonDetailsModal.vue b/src/features/admin/users/components/verifications/modals/RejectReasonDetailsModal.vue
new file mode 100644
index 0000000..c5712e8
--- /dev/null
+++ b/src/features/admin/users/components/verifications/modals/RejectReasonDetailsModal.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/verifications/modals/RejectReasonModal.vue b/src/features/admin/users/components/verifications/modals/RejectReasonModal.vue
new file mode 100644
index 0000000..cdd8ddd
--- /dev/null
+++ b/src/features/admin/users/components/verifications/modals/RejectReasonModal.vue
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/components/verifications/modals/UserVerificationDetailsModal.vue b/src/features/admin/users/components/verifications/modals/UserVerificationDetailsModal.vue
new file mode 100644
index 0000000..b2993cc
--- /dev/null
+++ b/src/features/admin/users/components/verifications/modals/UserVerificationDetailsModal.vue
@@ -0,0 +1,491 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/pages/UserFormPage.vue b/src/features/admin/users/pages/UserFormPage.vue
new file mode 100644
index 0000000..57efd44
--- /dev/null
+++ b/src/features/admin/users/pages/UserFormPage.vue
@@ -0,0 +1,486 @@
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/pages/UserVerificationPage.vue b/src/features/admin/users/pages/UserVerificationPage.vue
new file mode 100644
index 0000000..393b0de
--- /dev/null
+++ b/src/features/admin/users/pages/UserVerificationPage.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/pages/UsersListPage.vue b/src/features/admin/users/pages/UsersListPage.vue
new file mode 100644
index 0000000..07296d6
--- /dev/null
+++ b/src/features/admin/users/pages/UsersListPage.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/admin/users/schema/index.js b/src/features/admin/users/schema/index.js
new file mode 100644
index 0000000..980571c
--- /dev/null
+++ b/src/features/admin/users/schema/index.js
@@ -0,0 +1,40 @@
+import { object, string } from 'yup'
+
+import { phoneNumberRule } from '@/constants/rules/phoneNumberRule'
+import { nationalCodeRule } from '@/constants/rules/nationalCodeRule'
+import { passwordRule } from '@/constants/rules/passwordRule'
+import { passwordConfirmationRule } from '@/constants/rules/passwordConfirmationRule'
+
+export const rejectionReasonSchema = object().shape({
+ rejectionReason: string().required(),
+ priority: object()
+ .shape({
+ id: string().required().default(null),
+ })
+ .required()
+ .default(null),
+ adminNote: string().notRequired(),
+})
+
+const baseUserShape = {
+ roleId: string().required(),
+ firstName: string().required().min(2),
+ lastName: string().required().min(2),
+ phoneNumber: phoneNumberRule,
+ nationalCode: nationalCodeRule,
+ birthDate: string().nullable().notRequired(),
+ maritalStatus: string().nullable().notRequired(),
+ gender: string().nullable().notRequired(),
+ bio: string().nullable().notRequired(),
+ provinceId: string().nullable().notRequired(),
+ cityId: string().nullable().notRequired(),
+ address: string().nullable().notRequired(),
+}
+
+export const userAddSchema = object().shape({
+ ...baseUserShape,
+ password: passwordRule,
+ passwordConfirmation: passwordConfirmationRule,
+})
+
+export const userEditSchema = object().shape(baseUserShape)
diff --git a/src/features/auth/components/AuthCopyright.vue b/src/features/auth/components/AuthCopyright.vue
new file mode 100644
index 0000000..b781e3a
--- /dev/null
+++ b/src/features/auth/components/AuthCopyright.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/AuthHeading.vue b/src/features/auth/components/AuthHeading.vue
new file mode 100644
index 0000000..49640d1
--- /dev/null
+++ b/src/features/auth/components/AuthHeading.vue
@@ -0,0 +1,53 @@
+
+
+
![banu]()
+
{{ title }}
+
+ {{ subtitle }}
+
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/AuthShell.vue b/src/features/auth/components/AuthShell.vue
new file mode 100644
index 0000000..33712d4
--- /dev/null
+++ b/src/features/auth/components/AuthShell.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/LoginForm.vue b/src/features/auth/components/LoginForm.vue
new file mode 100644
index 0000000..2c06fb6
--- /dev/null
+++ b/src/features/auth/components/LoginForm.vue
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/LoginWithVerifyCodeForm.vue b/src/features/auth/components/LoginWithVerifyCodeForm.vue
new file mode 100644
index 0000000..64b609c
--- /dev/null
+++ b/src/features/auth/components/LoginWithVerifyCodeForm.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/PatternSection.vue b/src/features/auth/components/PatternSection.vue
new file mode 100644
index 0000000..e99671c
--- /dev/null
+++ b/src/features/auth/components/PatternSection.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
![banu]()
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/SignupForm.vue b/src/features/auth/components/SignupForm.vue
new file mode 100644
index 0000000..70f137a
--- /dev/null
+++ b/src/features/auth/components/SignupForm.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/components/VerifyCodeForm.vue b/src/features/auth/components/VerifyCodeForm.vue
new file mode 100644
index 0000000..bc882a2
--- /dev/null
+++ b/src/features/auth/components/VerifyCodeForm.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
diff --git a/src/features/auth/composables/useRedirectAfterLogin.js b/src/features/auth/composables/useRedirectAfterLogin.js
new file mode 100644
index 0000000..eea6b83
--- /dev/null
+++ b/src/features/auth/composables/useRedirectAfterLogin.js
@@ -0,0 +1,22 @@
+import { useRoute, useRouter } from 'vue-router'
+
+import { useAuthStore } from '@/store/auth'
+
+export const useRedirectAfterLogin = () => {
+ const router = useRouter()
+ const route = useRoute()
+ const auth = useAuthStore()
+
+ return () => {
+ const redirect = route.query.redirect
+ if (redirect && typeof redirect === 'string') {
+ router.push(redirect).catch(() => router.push('/'))
+ return
+ }
+ const target =
+ auth.role === 'admin' ? { name: 'admin-dashboard' } : { name: 'student-dashboard' }
+ router.push(target).catch(() => router.push('/'))
+ }
+}
+
+export default useRedirectAfterLogin
diff --git a/src/features/auth/pages/LoginPage.vue b/src/features/auth/pages/LoginPage.vue
new file mode 100644
index 0000000..fe11ac9
--- /dev/null
+++ b/src/features/auth/pages/LoginPage.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/features/auth/pages/ResetPasswordPage.vue b/src/features/auth/pages/ResetPasswordPage.vue
new file mode 100644
index 0000000..b5b4829
--- /dev/null
+++ b/src/features/auth/pages/ResetPasswordPage.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/features/auth/pages/SignupPage.vue b/src/features/auth/pages/SignupPage.vue
new file mode 100644
index 0000000..2cad010
--- /dev/null
+++ b/src/features/auth/pages/SignupPage.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
diff --git a/src/features/auth/router.js b/src/features/auth/router.js
new file mode 100644
index 0000000..f53fad9
--- /dev/null
+++ b/src/features/auth/router.js
@@ -0,0 +1,20 @@
+export default [
+ {
+ path: '/login',
+ name: 'login',
+ component: () => import('@/features/auth/pages/LoginPage.vue'),
+ meta: { public: true, requiresGuest: true, layout: 'public', title: 'ورود' },
+ },
+ {
+ path: '/signup',
+ name: 'signup',
+ component: () => import('@/features/auth/pages/SignupPage.vue'),
+ meta: { public: true, requiresGuest: true, layout: 'public', title: 'ثبت نام' },
+ },
+ {
+ path: '/reset-password',
+ name: 'reset-password',
+ component: () => import('@/features/auth/pages/ResetPasswordPage.vue'),
+ meta: { public: true, layout: 'public', title: 'تنظیم رمز عبور جدید' },
+ },
+]
diff --git a/src/features/auth/schema/index.js b/src/features/auth/schema/index.js
new file mode 100644
index 0000000..9668dfa
--- /dev/null
+++ b/src/features/auth/schema/index.js
@@ -0,0 +1,31 @@
+import { object, string } from 'yup'
+
+import { phoneNumberRule } from '@/constants/rules/phoneNumberRule'
+import { passwordRule } from '@/constants/rules/passwordRule'
+import { passwordConfirmationRule } from '@/constants/rules/passwordConfirmationRule'
+
+export const loginSchema = object().shape({
+ phoneNumber: phoneNumberRule,
+ password: string().required(),
+})
+
+export const loginWithCodeSchema = object().shape({
+ phoneNumber: phoneNumberRule,
+})
+
+export const signupSchema = object().shape({
+ firstName: string().required().min(3),
+ lastName: string().required().min(3),
+ phoneNumber: phoneNumberRule,
+ password: passwordRule,
+ passwordConfirmation: passwordConfirmationRule,
+})
+
+export const verifyCodeSchema = object().shape({
+ verifyCode: string().required().max(5),
+})
+
+export const resetPasswordSchema = object().shape({
+ password: passwordRule,
+ passwordConfirmation: passwordConfirmationRule,
+})
diff --git a/src/features/global-components/components/ItemDetailsModal.vue b/src/features/global-components/components/ItemDetailsModal.vue
new file mode 100644
index 0000000..0d5136e
--- /dev/null
+++ b/src/features/global-components/components/ItemDetailsModal.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
- شناسه
+ - {{ data?.id }}
+
+
+
- توضیحات
+ - {{ data?.description || '—' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/global-components/components/SampleModal.vue b/src/features/global-components/components/SampleModal.vue
new file mode 100644
index 0000000..798f4ae
--- /dev/null
+++ b/src/features/global-components/components/SampleModal.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/global-components/pages/GlobalComponents.vue b/src/features/global-components/pages/GlobalComponents.vue
new file mode 100644
index 0000000..0dc2f36
--- /dev/null
+++ b/src/features/global-components/pages/GlobalComponents.vue
@@ -0,0 +1,578 @@
+
+
+
+
+
+ دکمهها
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ تصویر پروفایل
+
+
+ فایل کراپشده آماده آپلود: {{ lastCroppedName }}
+
+
+
+
+ دکمهٔ گرد
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ صفحهبندی
+
+ الگوی استاندارد لیستها:
+ usePagination
+ +
+ useQuery(['items', pagination])
+
+
+ -
+ {{ item.name }}
+
+
+
+
+
+ صفحهٔ {{ pagination.page }} از {{ totalPages }}
+
+
+
+
+
+
+
+
{{ data?.title }}
+
{{ data?.body }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/global-components/router.js b/src/features/global-components/router.js
new file mode 100644
index 0000000..92f8af1
--- /dev/null
+++ b/src/features/global-components/router.js
@@ -0,0 +1,8 @@
+export default [
+ {
+ path: '/global-components',
+ name: 'global-components',
+ component: () => import('@/features/global-components/pages/GlobalComponents.vue'),
+ meta: { public: true, layout: 'public', title: 'کامپوننتهای گلوبال' },
+ },
+]
diff --git a/src/features/global-components/schema/index.js b/src/features/global-components/schema/index.js
new file mode 100644
index 0000000..8d57d02
--- /dev/null
+++ b/src/features/global-components/schema/index.js
@@ -0,0 +1,18 @@
+import { object, string } from 'yup'
+
+import { phoneNumberRule } from '@/constants/rules/phoneNumberRule'
+import { nationalCodeRule } from '@/constants/rules/nationalCodeRule'
+
+export const sampleSchema = object().shape({
+ subject: string().required(),
+ note: string().required(),
+})
+
+export const demoFormSchema = object().shape({
+ fullName: string().required().min(3),
+ phoneNumber: phoneNumberRule,
+ nationalCode: nationalCodeRule,
+ bio: string().max(160).nullable().notRequired(),
+ province: string().required(),
+ birthDate: string().required(),
+})
diff --git a/src/features/landing/pages/LandingPage.vue b/src/features/landing/pages/LandingPage.vue
new file mode 100644
index 0000000..ec23d25
--- /dev/null
+++ b/src/features/landing/pages/LandingPage.vue
@@ -0,0 +1,29 @@
+
+
+
سایت اصلی دانشگاه
+
در حال توسعه...
+
+
+
+
+
+
diff --git a/src/features/landing/router.js b/src/features/landing/router.js
new file mode 100644
index 0000000..65b0456
--- /dev/null
+++ b/src/features/landing/router.js
@@ -0,0 +1,8 @@
+export default [
+ {
+ path: '/',
+ name: 'home',
+ component: () => import('@/features/landing/pages/LandingPage.vue'),
+ meta: { public: true, layout: 'public', title: 'صفحه اصلی' },
+ },
+]
diff --git a/src/features/student/components/StudentCourseItem.vue b/src/features/student/components/StudentCourseItem.vue
new file mode 100644
index 0000000..94e155d
--- /dev/null
+++ b/src/features/student/components/StudentCourseItem.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
![]()
+
+
+
+
+
+
+ دوره
+ {{ course.title }}
+
+
+
+ استاد:
+ {{ teacherName }}
+
+
+
+
+
+
+
+
+ {{ statusLabel }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/student/pages/EditProfilePage.vue b/src/features/student/pages/EditProfilePage.vue
new file mode 100644
index 0000000..0e51d4b
--- /dev/null
+++ b/src/features/student/pages/EditProfilePage.vue
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+
diff --git a/src/features/student/pages/StudentCourseDetailsPage.vue b/src/features/student/pages/StudentCourseDetailsPage.vue
new file mode 100644
index 0000000..18ad16d
--- /dev/null
+++ b/src/features/student/pages/StudentCourseDetailsPage.vue
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+ معدل دوره:
+ {{ course.averageScore }}
+
+
+ دوره
+ {{ course.title }}
+
+
+
+ استاد:
+ {{ teacherName }}
+
+
+
+
+ تاریخ شروع:
+ {{ startDate }}
+
+
+ تاریخ پایان:
+ {{ endDate }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ session.title }}
+
+ {{ session.sessionTypeFa }}
+
+ · {{ session.durationMinutes }} دقیقه
+
+
+
+
+ {{ session.statusLabel || sessionStatusLabel(session.status) }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/student/pages/StudentCoursesPage.vue b/src/features/student/pages/StudentCoursesPage.vue
new file mode 100644
index 0000000..65e2702
--- /dev/null
+++ b/src/features/student/pages/StudentCoursesPage.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/student/pages/StudentDashboardPage.vue b/src/features/student/pages/StudentDashboardPage.vue
new file mode 100644
index 0000000..0230764
--- /dev/null
+++ b/src/features/student/pages/StudentDashboardPage.vue
@@ -0,0 +1,69 @@
+
+
+
+
![flower]()
+
+
سلام بر شما
+
به سامانه موسسه بانو خوش آمدید.
+
+
+
+
این بخش در مراحل بعدی توسعه مییابد.
+
+
+
+
+
+
diff --git a/src/features/student/router.js b/src/features/student/router.js
new file mode 100644
index 0000000..06cbe2d
--- /dev/null
+++ b/src/features/student/router.js
@@ -0,0 +1,26 @@
+export default [
+ {
+ path: '/dashboard',
+ name: 'student-dashboard',
+ component: () => import('@/features/student/pages/StudentDashboardPage.vue'),
+ meta: { layout: 'student', role: 'student', title: 'پیشخوان' },
+ },
+ {
+ path: '/profile',
+ name: 'student-profile',
+ component: () => import('@/features/student/pages/EditProfilePage.vue'),
+ meta: { layout: 'student', role: 'student', title: 'ویرایش پروفایل' },
+ },
+ {
+ path: '/my-courses',
+ name: 'student-courses',
+ component: () => import('@/features/student/pages/StudentCoursesPage.vue'),
+ meta: { layout: 'student', role: 'student', title: 'دورههای من' },
+ },
+ {
+ path: '/my-courses/:id',
+ name: 'student-course-details',
+ component: () => import('@/features/student/pages/StudentCourseDetailsPage.vue'),
+ meta: { layout: 'student', role: 'student', title: 'جزئیات دوره' },
+ },
+]
diff --git a/src/features/student/schema/index.js b/src/features/student/schema/index.js
new file mode 100644
index 0000000..e591604
--- /dev/null
+++ b/src/features/student/schema/index.js
@@ -0,0 +1,22 @@
+import { object, string } from 'yup'
+
+import { phoneNumberRule } from '@/constants/rules/phoneNumberRule'
+import { nationalCodeRule } from '@/constants/rules/nationalCodeRule'
+import { optionalPasswordRule } from '@/constants/rules/passwordRule'
+import { optionalPasswordConfirmationRule } from '@/constants/rules/passwordConfirmationRule'
+
+export const studentProfileSchema = object().shape({
+ firstName: string().required().min(2),
+ lastName: string().required().min(2),
+ phoneNumber: phoneNumberRule,
+ nationalCode: nationalCodeRule,
+ birthDate: string().nullable().notRequired(),
+ maritalStatus: string().nullable().notRequired(),
+ gender: string().nullable().notRequired(),
+ bio: string().nullable().notRequired(),
+ provinceId: string().nullable().notRequired(),
+ cityId: string().nullable().notRequired(),
+ address: string().nullable().notRequired(),
+ password: optionalPasswordRule,
+ passwordConfirmation: optionalPasswordConfirmationRule,
+})
diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue
new file mode 100644
index 0000000..f088c89
--- /dev/null
+++ b/src/layouts/AdminLayout.vue
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/PublicLayout.vue b/src/layouts/PublicLayout.vue
new file mode 100644
index 0000000..04de11a
--- /dev/null
+++ b/src/layouts/PublicLayout.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/StudentLayout.vue b/src/layouts/StudentLayout.vue
new file mode 100644
index 0000000..a4d4cd3
--- /dev/null
+++ b/src/layouts/StudentLayout.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/sidebars/AdminSidebar.vue b/src/layouts/sidebars/AdminSidebar.vue
new file mode 100644
index 0000000..7c5b71c
--- /dev/null
+++ b/src/layouts/sidebars/AdminSidebar.vue
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/sidebars/StudentSidebar.vue b/src/layouts/sidebars/StudentSidebar.vue
new file mode 100644
index 0000000..92d7d02
--- /dev/null
+++ b/src/layouts/sidebars/StudentSidebar.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..905ea74
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,51 @@
+import { createApp } from 'vue'
+import { createPinia } from 'pinia'
+import { MutationCache, QueryCache, QueryClient, VueQueryPlugin } from '@tanstack/vue-query'
+import Vue3Toastify from 'vue3-toastify'
+
+import App from '@/App.vue'
+import router from '@/router'
+import { globalComponents } from '@/utils/global-components'
+import { handleError } from '@/utils/error-handler'
+import { http } from '@/services/api'
+import { setupMocks } from '@/services/mock'
+
+import 'vue3-toastify/dist/index.css'
+import '@/assets/main.scss'
+import '@/utils/yup-locale'
+
+setupMocks(http)
+
+const app = createApp(App)
+const pinia = createPinia()
+
+Object.entries(globalComponents).forEach(([name, component]) => app.component(name, component))
+
+const queryClient = new QueryClient({
+ queryCache: new QueryCache({ onError: (error) => handleError(error) }),
+ mutationCache: new MutationCache({ onError: (error) => handleError(error) }),
+ defaultOptions: {
+ queries: {
+ retry: false,
+ staleTime: 5 * 60 * 1000,
+ refetchInterval: false,
+ refetchOnMount: false,
+ refetchOnWindowFocus: false,
+ gcTime: 5 * 60 * 1000,
+ },
+ },
+})
+
+app.use(VueQueryPlugin, { queryClient })
+
+app.use(Vue3Toastify, {
+ theme: 'colored',
+ type: 'default',
+ position: 'bottom-right',
+ autoClose: 1500,
+ transition: 'slide',
+ rtl: true,
+ dangerouslyHTMLString: true,
+})
+
+app.use(router).use(pinia).mount('#app')
diff --git a/src/router/guards.js b/src/router/guards.js
new file mode 100644
index 0000000..f4f2f8d
--- /dev/null
+++ b/src/router/guards.js
@@ -0,0 +1,40 @@
+import { tokenService } from '@/services/api/token-service'
+import { useAuthStore } from '@/store/auth'
+
+const APP_TITLE = 'بنو'
+
+const isPublic = (to) => to.meta?.public === true
+
+export const authGuard = (to) => {
+ if (isPublic(to)) return
+ if (to.meta?.requiresGuest) return
+ if (!tokenService.hasToken()) {
+ return { name: 'login', query: { redirect: to.fullPath } }
+ }
+ return
+}
+
+export const guestGuard = (to) => {
+ if (!to.meta?.requiresGuest) return
+ if (tokenService.hasToken()) {
+ const auth = useAuthStore()
+ return auth.role === 'admin' ? { name: 'admin-dashboard' } : { name: 'student-dashboard' }
+ }
+ return
+}
+
+export const roleGuard = (to) => {
+ if (!to.meta?.role) return
+ const auth = useAuthStore()
+ if (auth.role !== to.meta.role) {
+ return { name: 'home' }
+ }
+ return
+}
+
+export const titleGuard = (to) => {
+ const title = to.meta?.title
+ document.title = title ? `${APP_TITLE} - ${title}` : APP_TITLE
+}
+
+export const guards = [authGuard, guestGuard, roleGuard]
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..bc9e645
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,28 @@
+import { createRouter, createWebHistory } from 'vue-router'
+
+import { guards, titleGuard } from '@/router/guards'
+
+const routeModules = import.meta.glob('@/features/**/router.js', { eager: true })
+const routes = Object.values(routeModules).flatMap((mod) => mod.default || [])
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes: [...routes, { path: '/:pathMatch(.*)*', redirect: { name: 'home' } }],
+ scrollBehavior(to, from, savedPosition) {
+ if (savedPosition) return savedPosition
+ if (to.hash) return { el: to.hash }
+ return { top: 0 }
+ },
+})
+
+// router.beforeEach((to, from) => {
+// for (const guard of guards) {
+// const result = guard(to, from)
+// if (result !== undefined) return result
+// }
+// return
+// })
+
+router.afterEach((to) => titleGuard(to))
+
+export default router
diff --git a/src/services/api/admin-assignments.js b/src/services/api/admin-assignments.js
new file mode 100644
index 0000000..916c2a0
--- /dev/null
+++ b/src/services/api/admin-assignments.js
@@ -0,0 +1,23 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminAssignments = (params) => http.get(endpoints.getAssignmentsList, { params })
+
+export const apiShowAdminAssignment = (id) => http.get(buildUrl(endpoints.showAssignment, { id }))
+
+export const apiAddAdminAssignment = (payload) => http.post(endpoints.addNewAssignment, payload)
+
+export const apiUpdateAdminAssignment = (id, payload) =>
+ http.put(buildUrl(endpoints.updateAssignment, { id }), payload)
+
+export const apiDeleteAdminAssignment = (id) =>
+ http.delete(buildUrl(endpoints.deleteAssignment, { id }))
+
+export const apiGetAdminAssignmentSubmissions = (assignmentId, params) =>
+ http.get(buildUrl(endpoints.getAssignmentSubmissions, { assignmentId }), { params })
+
+export const apiShowAdminAssignmentSubmission = (assignmentId, submissionId) =>
+ http.get(buildUrl(endpoints.showAssignmentSubmission, { assignmentId, submissionId }))
+
+export const apiReviewAdminAssignmentSubmission = (assignmentId, submissionId, payload) =>
+ http.post(buildUrl(endpoints.reviewAssignmentSubmission, { assignmentId, submissionId }), payload)
diff --git a/src/services/api/admin-consultations.js b/src/services/api/admin-consultations.js
new file mode 100644
index 0000000..4abe00a
--- /dev/null
+++ b/src/services/api/admin-consultations.js
@@ -0,0 +1,14 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminConsultations = (params) =>
+ http.get(endpoints.getConsultationsList, { params })
+
+export const apiShowAdminConsultation = (id) =>
+ http.get(buildUrl(endpoints.showConsultation, { id }))
+
+export const apiSendAdminConsultationMessage = (id, payload) =>
+ http.post(buildUrl(endpoints.sendConsultationMessage, { id }), payload)
+
+export const apiChangeAdminConsultationStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeConsultationStatus, { id }), payload)
diff --git a/src/services/api/admin-course-templates.js b/src/services/api/admin-course-templates.js
new file mode 100644
index 0000000..d161730
--- /dev/null
+++ b/src/services/api/admin-course-templates.js
@@ -0,0 +1,38 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminCourseTemplates = (params) =>
+ http.get(endpoints.getCourseTemplatesList, { params })
+
+export const apiShowAdminCourseTemplate = (id) =>
+ http.get(buildUrl(endpoints.showCourseTemplate, { id }))
+
+export const apiAddAdminCourseTemplate = (payload) =>
+ http.post(endpoints.addNewCourseTemplate, payload)
+
+export const apiUpdateAdminCourseTemplate = (id, payload) =>
+ http.put(buildUrl(endpoints.updateCourseTemplate, { id }), payload)
+
+export const apiDeleteAdminCourseTemplate = (id) =>
+ http.delete(buildUrl(endpoints.deleteCourseTemplate, { id }))
+
+export const apiChangeAdminCourseTemplateStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeStatusCourseTemplate, { id }), payload)
+
+export const apiGetAdminTemplateStudents = (templateId, params) =>
+ http.get(buildUrl(endpoints.listTemplateStudents, { templateId }), { params })
+
+export const apiAddAdminTemplateStudent = (templateId, payload) =>
+ http.post(buildUrl(endpoints.addTemplateStudent, { templateId }), payload)
+
+export const apiRemoveAdminTemplateStudent = (templateId, userId) =>
+ http.delete(buildUrl(endpoints.removeTemplateStudent, { templateId, userId }))
+
+export const apiGetAdminTemplateSessions = (templateId, params) =>
+ http.get(buildUrl(endpoints.listTemplateSessions, { templateId }), { params })
+
+export const apiAttachAdminTemplateSession = (templateId, payload) =>
+ http.post(buildUrl(endpoints.attachTemplateSession, { templateId }), payload)
+
+export const apiDetachAdminTemplateSession = (templateId, sessionId) =>
+ http.delete(buildUrl(endpoints.detachTemplateSession, { templateId, sessionId }))
diff --git a/src/services/api/admin-courses.js b/src/services/api/admin-courses.js
new file mode 100644
index 0000000..f7e00a0
--- /dev/null
+++ b/src/services/api/admin-courses.js
@@ -0,0 +1,16 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminCourses = (params) => http.get(endpoints.getCoursesList, { params })
+
+export const apiShowAdminCourse = (id) => http.get(buildUrl(endpoints.showCourse, { id }))
+
+export const apiAddAdminCourse = (payload) => http.post(endpoints.addNewCourse, payload)
+
+export const apiUpdateAdminCourse = (id, payload) =>
+ http.put(buildUrl(endpoints.updateCourse, { id }), payload)
+
+export const apiDeleteAdminCourse = (id) => http.delete(buildUrl(endpoints.deleteCourse, { id }))
+
+export const apiChangeAdminCourseStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeStatusCourse, { id }), payload)
diff --git a/src/services/api/admin-exams.js b/src/services/api/admin-exams.js
new file mode 100644
index 0000000..a8617cc
--- /dev/null
+++ b/src/services/api/admin-exams.js
@@ -0,0 +1,19 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminExams = (params) => http.get(endpoints.getExamsList, { params })
+
+export const apiShowAdminExam = (id) => http.get(buildUrl(endpoints.showExam, { id }))
+
+export const apiAddAdminExam = (payload) => http.post(endpoints.addNewExam, payload)
+
+export const apiUpdateAdminExam = (id, payload) =>
+ http.put(buildUrl(endpoints.updateExam, { id }), payload)
+
+export const apiDeleteAdminExam = (id) => http.delete(buildUrl(endpoints.deleteExam, { id }))
+
+export const apiGetAdminExamParticipants = (examId, params) =>
+ http.get(buildUrl(endpoints.getExamParticipants, { examId }), { params })
+
+export const apiShowAdminExamParticipant = (examId, participantId) =>
+ http.get(buildUrl(endpoints.showExamParticipant, { examId, participantId }))
diff --git a/src/services/api/admin-pending-students.js b/src/services/api/admin-pending-students.js
new file mode 100644
index 0000000..ae7e454
--- /dev/null
+++ b/src/services/api/admin-pending-students.js
@@ -0,0 +1,13 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetPendingStudents = (params) => http.get(endpoints.getPendingStudents, { params })
+
+export const apiShowPendingStudent = (id) =>
+ http.get(buildUrl(endpoints.showPendingStudent, { id }))
+
+export const apiChangePendingStudentStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeStatusPendingStudent, { id }), payload)
+
+export const apiDownloadPendingStudentPdf = (id) =>
+ http.get(buildUrl(endpoints.downloadPdfPendingStudentInfo, { id }))
diff --git a/src/services/api/admin-sessions.js b/src/services/api/admin-sessions.js
new file mode 100644
index 0000000..ec122ee
--- /dev/null
+++ b/src/services/api/admin-sessions.js
@@ -0,0 +1,19 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminSessions = (params) => http.get(endpoints.getSessionsList, { params })
+
+export const apiShowAdminSession = (id) => http.get(buildUrl(endpoints.showSession, { id }))
+
+export const apiAddAdminSession = (payload) => http.post(endpoints.addNewSession, payload)
+
+export const apiUpdateAdminSession = (id, payload) =>
+ http.put(buildUrl(endpoints.updateSession, { id }), payload)
+
+export const apiDeleteAdminSession = (id) => http.delete(buildUrl(endpoints.deleteSession, { id }))
+
+export const apiChangeAdminSessionStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeStatusSession, { id }), payload)
+
+export const apiGetSessionAttendance = (sessionId, params) =>
+ http.get(buildUrl(endpoints.getSessionsAttendance, { sessionId }), { params })
diff --git a/src/services/api/admin-terms.js b/src/services/api/admin-terms.js
new file mode 100644
index 0000000..9e53453
--- /dev/null
+++ b/src/services/api/admin-terms.js
@@ -0,0 +1,39 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminTerms = (params) => http.get(endpoints.getTermsList, { params })
+
+export const apiShowAdminTerm = (id) => http.get(buildUrl(endpoints.showTerm, { id }))
+
+export const apiAddAdminTerm = (payload) => http.post(endpoints.addNewTerm, payload)
+
+export const apiUpdateAdminTerm = (id, payload) =>
+ http.put(buildUrl(endpoints.updateTerm, { id }), payload)
+
+export const apiDeleteAdminTerm = (id) => http.delete(buildUrl(endpoints.deleteTerm, { id }))
+
+export const apiCloneAdminTerm = (id) => http.post(buildUrl(endpoints.cloneTerm, { id }))
+
+export const apiChangeAdminTermStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeStatusTerm, { id }), payload)
+
+export const apiGetAdminTermStudents = (termId, params) =>
+ http.get(buildUrl(endpoints.listUserTerm, { termId }), { params })
+
+export const apiAddAdminTermStudents = (termId, payload) =>
+ http.post(buildUrl(endpoints.addUserTerm, { termId }), payload)
+
+export const apiRemoveAdminTermStudent = (termId, userId) =>
+ http.delete(buildUrl(endpoints.removeUserTerm, { termId, userId }))
+
+export const apiToggleAdminTermStudentLeave = (termId, userId, payload) =>
+ http.post(buildUrl(endpoints.changeLeaveStatus, { termId, userId }), payload)
+
+export const apiGetAdminTermCourses = (termId, params) =>
+ http.get(buildUrl(endpoints.listCourseTerm, { termId }), { params })
+
+export const apiAddAdminTermCourses = (termId, payload) =>
+ http.post(buildUrl(endpoints.addCourseTerm, { termId }), payload)
+
+export const apiRemoveAdminTermCourse = (termId, courseId) =>
+ http.delete(buildUrl(endpoints.removeCourseTerm, { termId, courseId }))
diff --git a/src/services/api/admin-tickets.js b/src/services/api/admin-tickets.js
new file mode 100644
index 0000000..28ed424
--- /dev/null
+++ b/src/services/api/admin-tickets.js
@@ -0,0 +1,12 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminTickets = (params) => http.get(endpoints.getTicketsList, { params })
+
+export const apiShowAdminTicket = (id) => http.get(buildUrl(endpoints.showTicket, { id }))
+
+export const apiSendAdminTicketMessage = (id, payload) =>
+ http.post(buildUrl(endpoints.sendTicketMessage, { id }), payload)
+
+export const apiChangeAdminTicketStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeTicketStatus, { id }), payload)
diff --git a/src/services/api/admin-users.js b/src/services/api/admin-users.js
new file mode 100644
index 0000000..e1e684f
--- /dev/null
+++ b/src/services/api/admin-users.js
@@ -0,0 +1,21 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetAdminUsers = (params) => http.get(endpoints.getApprovedUsers, { params })
+
+export const apiShowAdminUser = (id) => http.get(buildUrl(endpoints.showUserDetails, { id }))
+
+export const apiAddAdminUser = (payload) => http.post(endpoints.addNewUser, payload)
+
+export const apiUpdateAdminUser = (id, payload) =>
+ http.put(buildUrl(endpoints.updateUser, { id }), payload)
+
+export const apiUpdateAdminUserRole = (id, payload) =>
+ http.post(buildUrl(endpoints.updateUserRole, { id }), payload)
+
+export const apiChangeAdminUserStatus = (id, payload) =>
+ http.post(buildUrl(endpoints.changeUserStatus, { id }), payload)
+
+export const apiDeleteAdminUser = (id) => http.delete(buildUrl(endpoints.deleteUser, { id }))
+
+export const apiGetAdminRoles = () => http.get(endpoints.getRolesList)
diff --git a/src/services/api/auth.js b/src/services/api/auth.js
new file mode 100644
index 0000000..f1f8d16
--- /dev/null
+++ b/src/services/api/auth.js
@@ -0,0 +1,33 @@
+import { http } from '@/services/api/http'
+import { endpoints } from '@/services/api/endpoints'
+
+export const apiLogin = (payload) => http.post(endpoints.login, payload)
+
+export const apiLoginWithCode = (payload) => http.post(endpoints.loginWithCode2Step, payload)
+
+export const apiRegister = (payload) => http.post(endpoints.register, payload)
+
+export const apiVerifyCode = (payload) => http.post(endpoints.verifyCode, payload)
+
+export const apiResendVerificationCode = (payload) =>
+ http.post(endpoints.resendVerificationCodeForRegister, payload)
+
+export const apiForgotPassword = (payload) => http.post(endpoints.forgotPassword, payload)
+
+export const apiVerifyForgotPasswordCode = (payload) =>
+ http.post(endpoints.verifyForgotPasswordCode, payload)
+
+export const apiResetPassword = (payload) => http.post(endpoints.resetPassword, payload)
+
+export const apiLogout = () => http.post(endpoints.logout)
+
+export const apiGetProfile = () => http.get(endpoints.getProfile)
+
+export const apiCompleteProfile = (payload) => http.post(endpoints.completeProfile, payload)
+
+export const apiUpdateProfile = (payload) => http.put(endpoints.updateProfile, payload)
+
+export const apiGetRegistrationQuestionVideo = () =>
+ http.get(endpoints.getRegistrationQuestionVideo)
+
+export const apiUploadTemporary = (formData) => http.post(endpoints.uploadMediaTemporary, formData)
diff --git a/src/services/api/common.js b/src/services/api/common.js
new file mode 100644
index 0000000..cd87da4
--- /dev/null
+++ b/src/services/api/common.js
@@ -0,0 +1,7 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetProvinces = () => http.get(endpoints.provinceList)
+
+export const apiGetCitiesOfProvince = (provinceId) =>
+ http.get(buildUrl(endpoints.citiesList, { provinceId }))
diff --git a/src/services/api/endpoints.js b/src/services/api/endpoints.js
new file mode 100644
index 0000000..143a2a3
--- /dev/null
+++ b/src/services/api/endpoints.js
@@ -0,0 +1,117 @@
+export const endpoints = {
+ register: '/register',
+ resendVerificationCodeForRegister: '/resend-verification-code',
+ verifyCode: '/verify-code',
+ completeProfile: '/complete-profile',
+ getRegistrationQuestionVideo: '/verification-registration-media',
+ login: '/login',
+ loginWithCode2Step: '/login-with-code',
+ forgotPassword: '/forgot-password',
+ verifyForgotPasswordCode: '/verify-forgot-password-code',
+ resetPassword: '/reset-password',
+ logout: '/logout',
+ uploadMediaTemporary: '/upload-temp',
+
+ provinceList: '/provinces',
+ citiesList: '/provinces/:provinceId/cities',
+
+ getProfile: '/profile',
+ updateProfile: '/profile',
+ getStudentCourses: '/student/courses',
+ showStudentCourse: '/student/courses/:id',
+
+ getPendingStudents: '/admin/pending-students',
+ showPendingStudent: '/admin/pending-students/:id',
+ changeStatusPendingStudent: '/admin/pending-students/:id/status',
+ downloadPdfPendingStudentInfo: '/admin/pending-students/:id/pdf',
+ getApprovedUsers: '/admin/users',
+
+ showUserDetails: '/admin/users/:id',
+ addNewUser: '/admin/users',
+ updateUser: '/admin/users/:id',
+ updateUserRole: '/admin/users/:id/role',
+ getRolesList: '/admin/roles',
+ changeUserStatus: '/admin/users/:id/status',
+ deleteUser: '/admin/users/:id',
+
+ getTermsList: '/admin/terms',
+ addNewTerm: '/admin/terms',
+ showTerm: '/admin/terms/:id',
+ updateTerm: '/admin/terms/:id',
+ deleteTerm: '/admin/terms/:id',
+ cloneTerm: '/admin/terms/:id/clone',
+ changeStatusTerm: '/admin/terms/:id/status',
+
+ listUserTerm: '/admin/terms/:termId/students',
+ addUserTerm: '/admin/terms/:termId/students',
+ removeUserTerm: '/admin/terms/:termId/students/:userId',
+ changeLeaveStatus: '/admin/terms/:termId/students/:userId/toggle-leave',
+
+ listCourseTerm: '/admin/terms/:termId/courses',
+ addCourseTerm: '/admin/terms/:termId/courses',
+ removeCourseTerm: '/admin/terms/:termId/courses/:courseId',
+
+ getCoursesList: '/admin/courses',
+ addNewCourse: '/admin/courses',
+ showCourse: '/admin/courses/:id',
+ updateCourse: '/admin/courses/:id',
+ deleteCourse: '/admin/courses/:id',
+ changeStatusCourse: '/admin/courses/:id/toggle-status',
+
+ getCourseTemplatesList: '/admin/course-templates',
+ addNewCourseTemplate: '/admin/course-templates',
+ showCourseTemplate: '/admin/course-templates/:id',
+ updateCourseTemplate: '/admin/course-templates/:id',
+ deleteCourseTemplate: '/admin/course-templates/:id',
+ changeStatusCourseTemplate: '/admin/course-templates/:id/status',
+
+ listTemplateStudents: '/admin/course-templates/:templateId/students',
+ addTemplateStudent: '/admin/course-templates/:templateId/students',
+ removeTemplateStudent: '/admin/course-templates/:templateId/students/:userId',
+
+ listTemplateSessions: '/admin/course-templates/:templateId/sessions',
+ attachTemplateSession: '/admin/course-templates/:templateId/sessions',
+ detachTemplateSession: '/admin/course-templates/:templateId/sessions/:sessionId',
+
+ getSessionsList: '/admin/sessions',
+ addNewSession: '/admin/sessions',
+ showSession: '/admin/sessions/:id',
+ updateSession: '/admin/sessions/:id',
+ deleteSession: '/admin/sessions/:id',
+ changeStatusSession: '/admin/sessions/:id/toggle-status',
+
+ getSessionsAttendance: '/admin/sessions/:sessionId/attendances',
+
+ getAssignmentsList: '/admin/assignments',
+ addNewAssignment: '/admin/assignments',
+ showAssignment: '/admin/assignments/:id',
+ updateAssignment: '/admin/assignments/:id',
+ deleteAssignment: '/admin/assignments/:id',
+ getAssignmentSubmissions: '/admin/assignments/:assignmentId/submissions',
+ showAssignmentSubmission: '/admin/assignments/:assignmentId/submissions/:submissionId',
+ reviewAssignmentSubmission: '/admin/assignments/:assignmentId/submissions/:submissionId/review',
+
+ getTicketsList: '/admin/tickets',
+ showTicket: '/admin/tickets/:id',
+ sendTicketMessage: '/admin/tickets/:id/messages',
+ changeTicketStatus: '/admin/tickets/:id/status',
+
+ getConsultationsList: '/admin/consultations',
+ showConsultation: '/admin/consultations/:id',
+ sendConsultationMessage: '/admin/consultations/:id/messages',
+ changeConsultationStatus: '/admin/consultations/:id/status',
+
+ getExamsList: '/admin/exams',
+ addNewExam: '/admin/exams',
+ showExam: '/admin/exams/:id',
+ updateExam: '/admin/exams/:id',
+ deleteExam: '/admin/exams/:id',
+ getExamParticipants: '/admin/exams/:examId/participants',
+ showExamParticipant: '/admin/exams/:examId/participants/:participantId',
+}
+
+export const buildUrl = (template, params = {}) =>
+ Object.entries(params).reduce(
+ (url, [key, value]) => url.replace(`:${key}`, encodeURIComponent(value)),
+ template
+ )
diff --git a/src/services/api/http.js b/src/services/api/http.js
new file mode 100644
index 0000000..e64b761
--- /dev/null
+++ b/src/services/api/http.js
@@ -0,0 +1,99 @@
+import axios from 'axios'
+import { toast } from 'vue3-toastify'
+
+import { camelize, snakize } from '@/utils/convert-to-camel-snake'
+import { tokenService } from '@/services/api/token-service'
+
+const defaultHeaders = {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+}
+
+const addAuthTokenInterceptor = (instance) => {
+ instance.interceptors.request.use(
+ (config) => {
+ const token = tokenService.getToken()
+ const headers = {
+ ...config.headers,
+ Authorization: token ? `Bearer ${token}` : '',
+ }
+ if (config.data instanceof FormData) {
+ delete headers['Content-Type']
+ }
+ return { ...config, headers }
+ },
+ null,
+ { synchronous: true }
+ )
+}
+
+const addSnakizeInterceptor = (instance) => {
+ instance.interceptors.request.use(
+ (config) => {
+ if (config.data instanceof FormData || config.noSnakize) {
+ return config
+ }
+ return {
+ ...config,
+ params: config.params ? snakize(config.params) : {},
+ data: config.data ? snakize(config.data) : undefined,
+ }
+ },
+ (e) => Promise.reject(e)
+ )
+}
+
+const addResponseUnwrapInterceptor = (instance) => {
+ instance.interceptors.response.use(
+ (res) => {
+ if (typeof res?.data === 'number' || typeof res?.data === 'boolean') {
+ return { data: res.data }
+ }
+ return res?.data || res
+ },
+ (e) => Promise.reject(e)
+ )
+}
+
+const addCamelizeInterceptor = (instance) => {
+ instance.interceptors.response.use(
+ (res) => camelize(res),
+ (e) => Promise.reject(e)
+ )
+}
+
+const addUnauthorizeInterceptor = (instance) => {
+ instance.interceptors.response.use(
+ (res) => res,
+ async (e) => {
+ if (e?.response?.status === 401) {
+ tokenService.clearAll()
+ toast('نشست شما تایید نشد، لطفا مجدد وارد شوید')
+ try {
+ const { default: router } = await import('@/router')
+ router.push('/login').catch(() => {})
+ } catch {}
+ }
+ throw e
+ }
+ )
+}
+
+const createInstance = (baseUrl, { headers = {}, ...configs } = {}) => {
+ const instance = axios.create({
+ timeout: 15_000,
+ baseURL: baseUrl,
+ headers: { ...defaultHeaders, ...headers },
+ ...configs,
+ })
+ addAuthTokenInterceptor(instance)
+ addResponseUnwrapInterceptor(instance)
+ addCamelizeInterceptor(instance)
+ addSnakizeInterceptor(instance)
+ addUnauthorizeInterceptor(instance)
+ return instance
+}
+
+export const http = createInstance(import.meta.env.VITE_API_BASE_URL || '')
+
+export { createInstance }
diff --git a/src/services/api/index.js b/src/services/api/index.js
new file mode 100644
index 0000000..abd4a72
--- /dev/null
+++ b/src/services/api/index.js
@@ -0,0 +1,3 @@
+export { http, createInstance } from '@/services/api/http'
+export { endpoints, buildUrl } from '@/services/api/endpoints'
+export { tokenService } from '@/services/api/token-service'
diff --git a/src/services/api/student-courses.js b/src/services/api/student-courses.js
new file mode 100644
index 0000000..6c84698
--- /dev/null
+++ b/src/services/api/student-courses.js
@@ -0,0 +1,6 @@
+import { http } from '@/services/api/http'
+import { buildUrl, endpoints } from '@/services/api/endpoints'
+
+export const apiGetStudentCourses = (params) => http.get(endpoints.getStudentCourses, { params })
+
+export const apiShowStudentCourse = (id) => http.get(buildUrl(endpoints.showStudentCourse, { id }))
diff --git a/src/services/api/token-service.js b/src/services/api/token-service.js
new file mode 100644
index 0000000..62b1e7d
--- /dev/null
+++ b/src/services/api/token-service.js
@@ -0,0 +1,48 @@
+const TOKEN = 'user_token'
+const REFRESH_TOKEN = 'refresh_user_token'
+const USER_INFO = 'user_info'
+const STUDENT_REGISTRATION_INFO = 'StudentRegistration'
+
+export const tokenService = {
+ getToken() {
+ return localStorage.getItem(TOKEN)
+ },
+ saveToken(token) {
+ if (token) localStorage.setItem(TOKEN, token)
+ },
+ removeToken() {
+ localStorage.removeItem(TOKEN)
+ },
+
+ getRefreshToken() {
+ return localStorage.getItem(REFRESH_TOKEN)
+ },
+ saveRefreshToken(newToken) {
+ if (newToken) localStorage.setItem(REFRESH_TOKEN, newToken)
+ },
+ removeRefreshToken() {
+ localStorage.removeItem(REFRESH_TOKEN)
+ },
+
+ getUserInfo() {
+ const info = localStorage.getItem(USER_INFO)
+ return info ? JSON.parse(info) : null
+ },
+ saveUserInfo(info) {
+ if (info) localStorage.setItem(USER_INFO, JSON.stringify(info))
+ },
+ removeUserInfo() {
+ localStorage.removeItem(USER_INFO)
+ localStorage.removeItem(STUDENT_REGISTRATION_INFO)
+ },
+
+ hasToken() {
+ return !!this.getToken()
+ },
+
+ clearAll() {
+ this.removeToken()
+ this.removeRefreshToken()
+ this.removeUserInfo()
+ },
+}
diff --git a/src/services/mock/fixtures/.gitkeep b/src/services/mock/fixtures/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/services/mock/fixtures/admin-assignments.js b/src/services/mock/fixtures/admin-assignments.js
new file mode 100644
index 0000000..1a9227c
--- /dev/null
+++ b/src/services/mock/fixtures/admin-assignments.js
@@ -0,0 +1,96 @@
+export const adminAssignments = [
+ {
+ id: 301,
+ title: 'یادداشتبرداری از جلسه اول',
+ description: 'خلاصهای از مباحث جلسه اول را در دو صفحه بنویسید.',
+ courseTemplate: { id: 1, title: 'اصول اخلاق اسلامی' },
+ courseTemplateTitle: 'اصول اخلاق اسلامی',
+ session: { id: 101, title: 'مقدمهای بر اخلاق اسلامی' },
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ startDate: '2025-09-26T00:00:00.000Z',
+ endDate: '2025-10-05T23:59:00.000Z',
+ durationDays: 9,
+ priority: 'mandatory',
+ submissionsCount: 2,
+ attachments: [],
+ createdAt: '2025-09-24T08:00:00.000Z',
+ },
+ {
+ id: 302,
+ title: 'تحلیل تفسیری سوره حمد',
+ description: 'تحلیل سه آیه از سوره حمد را ارسال نمایید.',
+ courseTemplate: { id: 2, title: 'مفاهیم قرآنی' },
+ courseTemplateTitle: 'مفاهیم قرآنی',
+ session: { id: 102, title: 'تفسیر سوره حمد' },
+ sessionTitle: 'تفسیر سوره حمد',
+ startDate: '2025-10-05T00:00:00.000Z',
+ endDate: '2025-10-20T23:59:00.000Z',
+ durationDays: 15,
+ priority: 'optional',
+ submissionsCount: 1,
+ attachments: [],
+ createdAt: '2025-10-02T08:00:00.000Z',
+ },
+]
+
+export const assignmentSubmissions = new Map([
+ [
+ 301,
+ [
+ {
+ id: 1,
+ assignmentId: 301,
+ userId: 100,
+ user: {
+ id: 100,
+ firstName: 'فاطمه',
+ lastName: 'رضایی',
+ fullName: 'فاطمه رضایی',
+ avatarUrl: '',
+ address: { province: { name: 'تهران' }, city: { name: 'تهران' } },
+ profile: {
+ educationStatus: 'seminary_student',
+ seminaryLevel: 'level_3',
+ universityLevel: 'not_applicable',
+ },
+ },
+ termTitle: 'ترم پاییز ۱۴۰۴',
+ courseTemplateTitle: 'اصول اخلاق اسلامی',
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ userDescription: 'یادداشتهای جلسه اول به همراه برداشت شخصی ضمیمه است.',
+ attachments: [{ id: 1, title: 'یادداشت-جلسه-اول.pdf', fileUrl: '#', type: 'document' }],
+ submittedAt: '2025-10-02T18:30:00.000Z',
+ status: 'pending',
+ score: null,
+ reviewerNote: '',
+ },
+ {
+ id: 2,
+ assignmentId: 301,
+ userId: 102,
+ user: {
+ id: 102,
+ firstName: 'مریم',
+ lastName: 'احمدی',
+ fullName: 'مریم احمدی',
+ avatarUrl: '',
+ address: { province: { name: 'اصفهان' }, city: { name: 'اصفهان' } },
+ profile: {
+ educationStatus: 'seminary_and_university_student',
+ seminaryLevel: 'level_2',
+ universityLevel: 'bachelor',
+ },
+ },
+ termTitle: 'ترم پاییز ۱۴۰۴',
+ courseTemplateTitle: 'اصول اخلاق اسلامی',
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ userDescription: 'خلاصهای از جلسه به همراه پرسش پایان.',
+ attachments: [],
+ submittedAt: '2025-10-04T20:00:00.000Z',
+ status: 'approved',
+ score: 18,
+ reviewerNote: 'تحلیل خوبی ارائه شده است.',
+ },
+ ],
+ ],
+])
diff --git a/src/services/mock/fixtures/admin-consultations.js b/src/services/mock/fixtures/admin-consultations.js
new file mode 100644
index 0000000..24f54bf
--- /dev/null
+++ b/src/services/mock/fixtures/admin-consultations.js
@@ -0,0 +1,86 @@
+export const adminConsultations = [
+ {
+ id: 387,
+ requestId: '387',
+ user: {
+ id: 201,
+ firstName: 'علیرضا',
+ lastName: 'محمدی',
+ fullName: 'علیرضا محمدی',
+ avatarUrl: '',
+ },
+ status: 'answered',
+ statusLabel: 'پاسخ داده شده',
+ createdAt: '2026-05-12T13:54:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۲۲',
+ faCreatedTime: '۱۳:۵۴',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'سلام، در خصوص انتخاب رشته مشاوره میخواستم.',
+ time: '۱۳:۵۴',
+ },
+ {
+ id: 2,
+ sender: 'admin',
+ text: 'سلام و وقت بخیر، لطفا رشته فعلی و علاقهمندیهای خود را بفرمایید.',
+ time: '۱۴:۰۲',
+ },
+ ],
+ },
+ {
+ id: 388,
+ requestId: '388',
+ user: {
+ id: 202,
+ firstName: 'زهرا',
+ lastName: 'کریمی',
+ fullName: 'زهرا کریمی',
+ avatarUrl: '',
+ },
+ status: 'in_progress',
+ statusLabel: 'در حال گفتگو',
+ createdAt: '2026-05-11T09:30:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۲۱',
+ faCreatedTime: '۰۹:۳۰',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'برای ادامه تحصیل در سطح ۳ راهنمایی نیاز دارم.',
+ time: '۰۹:۳۰',
+ },
+ ],
+ },
+ {
+ id: 389,
+ requestId: '389',
+ user: {
+ id: 203,
+ firstName: 'محمد',
+ lastName: 'حسینی',
+ fullName: 'محمد حسینی',
+ avatarUrl: '',
+ },
+ status: 'closed',
+ statusLabel: 'بسته شده',
+ createdAt: '2026-05-09T16:10:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۱۹',
+ faCreatedTime: '۱۶:۱۰',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'مشاوره دریافت شد، با تشکر.',
+ time: '۱۶:۱۰',
+ },
+ {
+ id: 2,
+ sender: 'admin',
+ text: 'موفق باشید.',
+ time: '۱۶:۱۲',
+ },
+ ],
+ },
+]
diff --git a/src/services/mock/fixtures/admin-courses.js b/src/services/mock/fixtures/admin-courses.js
new file mode 100644
index 0000000..0cc31df
--- /dev/null
+++ b/src/services/mock/fixtures/admin-courses.js
@@ -0,0 +1,89 @@
+export const adminCourseTemplates = [
+ {
+ id: 1,
+ title: 'اصول اخلاق اسلامی',
+ description: 'دوره مقدماتی برای آشنایی با اخلاق اسلامی.',
+ image: 'https://picsum.photos/seed/course1/200/200',
+ defaultTeacher: { id: 5, firstName: 'علی', lastName: 'حسنی', fullName: 'علی حسنی' },
+ defaultCapacity: 30,
+ isActiveByDefault: true,
+ prerequisitesCount: 0,
+ prerequisites: [],
+ createdAt: '2025-08-10T08:00:00.000Z',
+ },
+ {
+ id: 2,
+ title: 'مفاهیم قرآنی',
+ description: 'بررسی مفاهیم قرآنی به همراه تفسیر مختصر.',
+ image: 'https://picsum.photos/seed/course2/200/200',
+ defaultTeacher: { id: 6, firstName: 'حسین', lastName: 'مرادی', fullName: 'حسین مرادی' },
+ defaultCapacity: 25,
+ isActiveByDefault: true,
+ prerequisitesCount: 1,
+ prerequisites: [{ courseId: 1, course: { id: 1, title: 'اصول اخلاق اسلامی' } }],
+ createdAt: '2025-09-12T08:00:00.000Z',
+ },
+ {
+ id: 3,
+ title: 'فقه عبادات',
+ description: 'مرور احکام عملی نماز و روزه.',
+ image: '',
+ defaultTeacher: { id: 7, firstName: 'مهدی', lastName: 'سهرابی', fullName: 'مهدی سهرابی' },
+ defaultCapacity: 20,
+ isActiveByDefault: false,
+ prerequisitesCount: 0,
+ prerequisites: [],
+ createdAt: '2026-01-05T08:00:00.000Z',
+ },
+]
+
+export const adminOfferedCourses = [
+ {
+ id: 11,
+ title: 'اصول اخلاق اسلامی - پاییز',
+ image: 'https://picsum.photos/seed/offered1/200/200',
+ template: { id: 1, title: 'اصول اخلاق اسلامی' },
+ templateId: 1,
+ term: { id: 1, title: 'ترم پاییز ۱۴۰۴' },
+ termId: 1,
+ teacher: { id: 5, firstName: 'علی', lastName: 'حسنی', fullName: 'علی حسنی' },
+ capacity: 30,
+ isActive: true,
+ prerequisitesCount: 0,
+ startDate: '2025-09-23T00:00:00.000Z',
+ endDate: '2025-11-20T00:00:00.000Z',
+ createdAt: '2025-09-01T08:00:00.000Z',
+ },
+ {
+ id: 12,
+ title: 'مفاهیم قرآنی - پاییز',
+ image: 'https://picsum.photos/seed/offered2/200/200',
+ template: { id: 2, title: 'مفاهیم قرآنی' },
+ templateId: 2,
+ term: { id: 1, title: 'ترم پاییز ۱۴۰۴' },
+ termId: 1,
+ teacher: { id: 6, firstName: 'حسین', lastName: 'مرادی', fullName: 'حسین مرادی' },
+ capacity: 25,
+ isActive: true,
+ prerequisitesCount: 1,
+ startDate: '2025-10-01T00:00:00.000Z',
+ endDate: '2025-12-15T00:00:00.000Z',
+ createdAt: '2025-09-10T08:00:00.000Z',
+ },
+ {
+ id: 13,
+ title: 'فقه عبادات - زمستان',
+ image: '',
+ template: { id: 3, title: 'فقه عبادات' },
+ templateId: 3,
+ term: { id: 2, title: 'ترم زمستان ۱۴۰۴' },
+ termId: 2,
+ teacher: { id: 7, firstName: 'مهدی', lastName: 'سهرابی', fullName: 'مهدی سهرابی' },
+ capacity: 20,
+ isActive: false,
+ prerequisitesCount: 0,
+ startDate: '2026-01-22T00:00:00.000Z',
+ endDate: '2026-03-15T00:00:00.000Z',
+ createdAt: '2025-12-10T08:00:00.000Z',
+ },
+]
diff --git a/src/services/mock/fixtures/admin-exams.js b/src/services/mock/fixtures/admin-exams.js
new file mode 100644
index 0000000..a3ee66b
--- /dev/null
+++ b/src/services/mock/fixtures/admin-exams.js
@@ -0,0 +1,123 @@
+const sampleQuestions = (seed) => [
+ {
+ id: `${seed}-q1`,
+ title: 'کدام گزینه به مفهوم تقوا نزدیکتر است؟',
+ score: 5,
+ correctAnswerId: `${seed}-q1-a2`,
+ answers: [
+ { id: `${seed}-q1-a1`, title: 'پرهیز از خطا و دوری از گناه' },
+ { id: `${seed}-q1-a2`, title: 'خودنگهداری در محضر خداوند' },
+ { id: `${seed}-q1-a3`, title: 'پرهیز از خوراکیهای مضر' },
+ ],
+ },
+ {
+ id: `${seed}-q2`,
+ title: 'منبع اصلی احکام شیعه چیست؟',
+ score: 5,
+ correctAnswerId: `${seed}-q2-a1`,
+ answers: [
+ { id: `${seed}-q2-a1`, title: 'قرآن و سنت اهل بیت(ع)' },
+ { id: `${seed}-q2-a2`, title: 'فقط قرآن کریم' },
+ { id: `${seed}-q2-a3`, title: 'اجماع علما' },
+ ],
+ },
+]
+
+export const adminExams = [
+ {
+ id: 201,
+ title: 'آزمون پایان فصل اول اخلاق',
+ description: 'آزمون چهار گزینهای از مفاهیم درسهای ۱ تا ۳.',
+ courseTemplate: { id: 1, title: 'اصول اخلاق اسلامی' },
+ courseTemplateTitle: 'اصول اخلاق اسلامی',
+ session: { id: 101, title: 'مقدمهای بر اخلاق اسلامی' },
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ durationMinutes: 25,
+ passingScore: 12,
+ questionsCount: 2,
+ randomize: true,
+ endDate: '2026-05-15T00:00:00.000Z',
+ startDate: '2026-05-01T00:00:00.000Z',
+ createdAt: '2026-04-20T08:00:00.000Z',
+ questions: sampleQuestions(201),
+ usedInTerms: [{ termId: 1 }],
+ },
+ {
+ id: 202,
+ title: 'آزمون مفاهیم قرآنی - میانترم',
+ description: 'آزمون میانترم برای مرور آیات کلیدی.',
+ courseTemplate: { id: 2, title: 'مفاهیم قرآنی' },
+ courseTemplateTitle: 'مفاهیم قرآنی',
+ session: { id: 102, title: 'تفسیر سوره حمد' },
+ sessionTitle: 'تفسیر سوره حمد',
+ durationMinutes: 30,
+ passingScore: 14,
+ questionsCount: 2,
+ randomize: false,
+ endDate: '2026-06-10T00:00:00.000Z',
+ startDate: '2026-05-25T00:00:00.000Z',
+ createdAt: '2026-05-10T08:00:00.000Z',
+ questions: sampleQuestions(202),
+ usedInTerms: [{ termId: 1 }],
+ },
+]
+
+export const examParticipants = new Map([
+ [
+ 201,
+ [
+ {
+ id: 1,
+ userId: 100,
+ firstName: 'فاطمه',
+ lastName: 'رضایی',
+ fullName: 'فاطمه رضایی',
+ avatarUrl: '',
+ address: { province: { name: 'تهران' }, city: { name: 'تهران' } },
+ location: 'تهران، تهران',
+ submittedAt: '2026-05-05T10:30:00.000Z',
+ attempts: [
+ {
+ id: 1,
+ title: 'تلاش اول',
+ courseTitle: 'اصول اخلاق اسلامی',
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ date: '2026-05-05T10:30:00.000Z',
+ score: 17,
+ scoreTone: 'good',
+ questions: sampleQuestions(201).map((q) => ({
+ ...q,
+ userAnswerId: q.correctAnswerId,
+ })),
+ },
+ ],
+ },
+ {
+ id: 2,
+ userId: 102,
+ firstName: 'مریم',
+ lastName: 'احمدی',
+ fullName: 'مریم احمدی',
+ avatarUrl: '',
+ address: { province: { name: 'اصفهان' }, city: { name: 'اصفهان' } },
+ location: 'اصفهان، اصفهان',
+ submittedAt: '2026-05-06T11:00:00.000Z',
+ attempts: [
+ {
+ id: 2,
+ title: 'تلاش اول',
+ courseTitle: 'اصول اخلاق اسلامی',
+ sessionTitle: 'مقدمهای بر اخلاق اسلامی',
+ date: '2026-05-06T11:00:00.000Z',
+ score: 9,
+ scoreTone: 'bad',
+ questions: sampleQuestions(201).map((q, i) => ({
+ ...q,
+ userAnswerId: i === 0 ? q.answers[0].id : q.correctAnswerId,
+ })),
+ },
+ ],
+ },
+ ],
+ ],
+])
diff --git a/src/services/mock/fixtures/admin-pending-students.js b/src/services/mock/fixtures/admin-pending-students.js
new file mode 100644
index 0000000..23e372a
--- /dev/null
+++ b/src/services/mock/fixtures/admin-pending-students.js
@@ -0,0 +1,65 @@
+const firstNames = ['سکینه', 'رقیه', 'فاطمه', 'مریم', 'لیلا', 'زهرا', 'فریده', 'نسرین']
+const lastNames = ['طاهری', 'سلیمی', 'افشار', 'بختیاری', 'خراسانی', 'سهرابی', 'محمدی', 'بهرامی']
+
+const pick = (arr, i) => arr[i % arr.length]
+
+const makeStudent = (i) => {
+ const firstName = pick(firstNames, i)
+ const lastName = pick(lastNames, i + 2)
+ const status = i % 3 === 0 ? 'rejected' : 'pending'
+ const submittedAt = new Date(Date.now() - i * 86_400_000).toISOString()
+ return {
+ id: 500 + i,
+ firstName,
+ lastName,
+ fullName: `${firstName} ${lastName}`,
+ phoneNumber: `0935${String(2_000_000 + i).padStart(7, '0')}`,
+ nationalCode: String(2_000_000_000 + i * 11).padStart(10, '0'),
+ avatarUrl: '',
+ status,
+ submittedAt,
+ address: {
+ address: 'آدرس نمونه',
+ province: { id: 1, name: 'تهران' },
+ city: { id: 11, name: 'تهران' },
+ },
+ profile: {
+ birthDate: new Date(1992, i % 12, ((i * 5) % 27) + 1).toISOString(),
+ maritalStatus: i % 2 ? 'single' : 'married',
+ gender: 'female',
+ educationStatus: 'seminary_student',
+ seminaryLevel: 'level_3',
+ universityLevel: 'not_applicable',
+ universityName: 'حوزه علمیه قم',
+ fieldOfStudy: 'فقه و اصول',
+ workExperienceSummary: 'پنج سال تدریس در مدرسه دینی.',
+ activitySummary: 'برگزاری جلسات قرآن و حدیث به صورت هفتگی.',
+ propagationExperienceYears: 6,
+ propagationMethodDescription: 'محوریت بیان داستانهای قرآنی و قرابتهای اخلاقی.',
+ specializedTopics: 'تربیت دینی نوجوانان',
+ propagationPlatforms: [
+ { platform: 'home_gathering_regular' },
+ { platform: 'online', platformDetails: 'کانال اینستاگرام @example' },
+ ],
+ responseToLowSatisfaction: 'change_the_method',
+ responseToSessionCancellation: 'teach_how_to_reduce_costs',
+ responseToAudienceConflict: 'divide_the_crowd',
+ responseToCompetingPropagator: 'strengthen_yourself',
+ responseToUnqualifiedAdvisors: 'تلاش بر شفافسازی و معرفی مراجع تخصصی.',
+ relevantCertificates: 'سطح ۳ حوزوی، تدریس قرآن',
+ hijabApproach: 'گفتگوی همدلانه و آموزشمحور.',
+ },
+ verification: {
+ status,
+ submittedAt,
+ rejectionReason: status === 'rejected' ? 'عدم تکمیل مدارک' : '',
+ adminNote: status === 'rejected' ? 'لطفا مدارک تحصیلی بهروز ارسال شود.' : '',
+ verifiedBy: { firstName: 'سجاد', lastName: 'محمدی' },
+ media: [],
+ },
+ roles: ['student'],
+ createdAt: submittedAt,
+ }
+}
+
+export const pendingStudents = Array.from({ length: 14 }, (_, i) => makeStudent(i))
diff --git a/src/services/mock/fixtures/admin-sessions.js b/src/services/mock/fixtures/admin-sessions.js
new file mode 100644
index 0000000..1811f7e
--- /dev/null
+++ b/src/services/mock/fixtures/admin-sessions.js
@@ -0,0 +1,107 @@
+export const adminSessions = [
+ {
+ id: 101,
+ title: 'مقدمهای بر اخلاق اسلامی',
+ description: 'جلسه نخست؛ تعاریف و چارچوب دوره.',
+ image: 'https://picsum.photos/seed/session1/200/200',
+ courseTemplate: { id: 1, title: 'اصول اخلاق اسلامی' },
+ sessionType: 'in_person',
+ sessionTypeFa: 'حضوری',
+ durationMinutes: 90,
+ order: 1,
+ sessionConfig: {
+ startTime: '2025-09-25T16:00:00.000Z',
+ location: 'سالن آمفیتئاتر ۲ - مدرسه قم',
+ },
+ materials: [],
+ usedInTerms: [{ termId: 1 }],
+ createdAt: '2025-09-10T08:00:00.000Z',
+ },
+ {
+ id: 102,
+ title: 'تفسیر سوره حمد',
+ description: 'تحلیل آیات سوره حمد.',
+ image: '',
+ courseTemplate: { id: 2, title: 'مفاهیم قرآنی' },
+ sessionType: 'online',
+ sessionTypeFa: 'آنلاین',
+ durationMinutes: 75,
+ order: 1,
+ sessionConfig: {
+ meetingLink: 'https://meet.example.com/quran-1',
+ platform: 'google_meet',
+ startTime: '2025-10-04T19:00:00.000Z',
+ },
+ materials: [],
+ usedInTerms: [{ termId: 1 }],
+ createdAt: '2025-09-25T08:00:00.000Z',
+ },
+ {
+ id: 103,
+ title: 'احکام نماز جماعت',
+ description: 'مرور احکام و شرایط نماز جماعت.',
+ image: '',
+ courseTemplate: { id: 3, title: 'فقه عبادات' },
+ sessionType: 'video',
+ sessionTypeFa: 'ویدئو',
+ durationMinutes: 50,
+ order: 2,
+ sessionConfig: {
+ minWatchedPercent: 80,
+ mustCompleteBeforeNext: true,
+ },
+ materials: [],
+ usedInTerms: [],
+ createdAt: '2026-01-12T08:00:00.000Z',
+ },
+]
+
+export const sessionAttendance = new Map([
+ [
+ 101,
+ [
+ {
+ id: 1,
+ userId: 100,
+ sessionId: 101,
+ status: 'present',
+ user: {
+ id: 100,
+ firstName: 'فاطمه',
+ lastName: 'رضایی',
+ fullName: 'فاطمه رضایی',
+ avatarUrl: '',
+ address: { province: { name: 'تهران' }, city: { name: 'تهران' } },
+ },
+ },
+ {
+ id: 2,
+ userId: 102,
+ sessionId: 101,
+ status: 'absent',
+ user: {
+ id: 102,
+ firstName: 'مریم',
+ lastName: 'احمدی',
+ fullName: 'مریم احمدی',
+ avatarUrl: '',
+ address: { province: { name: 'اصفهان' }, city: { name: 'اصفهان' } },
+ },
+ },
+ {
+ id: 3,
+ userId: 103,
+ sessionId: 101,
+ status: 'late',
+ user: {
+ id: 103,
+ firstName: 'علی',
+ lastName: 'علوی',
+ fullName: 'علی علوی',
+ avatarUrl: '',
+ address: { province: { name: 'تهران' }, city: { name: 'تهران' } },
+ },
+ },
+ ],
+ ],
+])
diff --git a/src/services/mock/fixtures/admin-terms.js b/src/services/mock/fixtures/admin-terms.js
new file mode 100644
index 0000000..fc41325
--- /dev/null
+++ b/src/services/mock/fixtures/admin-terms.js
@@ -0,0 +1,57 @@
+export const adminTerms = [
+ {
+ id: 1,
+ title: 'ترم پاییز ۱۴۰۴',
+ description: 'ترم پاییز با محوریت آموزش معارف اسلامی.',
+ image: 'https://picsum.photos/seed/term1/200/200',
+ startDate: '2025-09-23T00:00:00.000Z',
+ endDate: '2026-01-20T00:00:00.000Z',
+ isActive: true,
+ studentsCount: 18,
+ coursesCount: 4,
+ createdAt: '2025-08-01T08:00:00.000Z',
+ },
+ {
+ id: 2,
+ title: 'ترم زمستان ۱۴۰۴',
+ description: 'ترم زمستان با تمرکز بر فقه و اصول.',
+ image: 'https://picsum.photos/seed/term2/200/200',
+ startDate: '2026-01-21T00:00:00.000Z',
+ endDate: '2026-04-20T00:00:00.000Z',
+ isActive: true,
+ studentsCount: 12,
+ coursesCount: 3,
+ createdAt: '2025-11-10T08:00:00.000Z',
+ },
+ {
+ id: 3,
+ title: 'ترم بهار ۱۴۰۵',
+ description: 'ترم بهار ویژه دورههای تخصصی.',
+ image: '',
+ startDate: '2026-04-21T00:00:00.000Z',
+ endDate: '2026-08-21T00:00:00.000Z',
+ isActive: false,
+ studentsCount: 0,
+ coursesCount: 2,
+ createdAt: '2026-02-15T08:00:00.000Z',
+ },
+]
+
+export const termStudentLinks = new Map([
+ [
+ 1,
+ [
+ { userId: 100, isOnLeave: false },
+ { userId: 101, isOnLeave: false },
+ { userId: 102, isOnLeave: true },
+ { userId: 103, isOnLeave: false },
+ ],
+ ],
+ [
+ 2,
+ [
+ { userId: 104, isOnLeave: false },
+ { userId: 105, isOnLeave: false },
+ ],
+ ],
+])
diff --git a/src/services/mock/fixtures/admin-tickets.js b/src/services/mock/fixtures/admin-tickets.js
new file mode 100644
index 0000000..30fbe3e
--- /dev/null
+++ b/src/services/mock/fixtures/admin-tickets.js
@@ -0,0 +1,92 @@
+export const adminTickets = [
+ {
+ id: 401,
+ title: 'پیگیری وضعیت ثبتنام',
+ user: {
+ id: 100,
+ firstName: 'فاطمه',
+ lastName: 'رضایی',
+ fullName: 'فاطمه رضایی',
+ avatarUrl: '',
+ },
+ status: 'answered',
+ statusLabel: 'پاسخ داده شده',
+ createdAt: '2026-05-09T20:28:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۱۹',
+ faCreatedTime: '۱۰:۳۰',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'سلام وقت بخیر، در فرایند ثبتنام به مشکل برخوردم.',
+ time: '۱۲:۳۵',
+ },
+ {
+ id: 2,
+ sender: 'admin',
+ text: 'سلام و عرض ادب. لطفا کد پیگیری ثبتنام را ارسال کنید.',
+ time: '۱۲:۴۰',
+ },
+ {
+ id: 3,
+ sender: 'user',
+ text: 'کد ثبتنام: ۱۲۳۴۵۶۷۸',
+ time: '۱۲:۴۲',
+ },
+ ],
+ },
+ {
+ id: 402,
+ title: 'سوال درباره جلسه آموزشی',
+ user: {
+ id: 102,
+ firstName: 'مریم',
+ lastName: 'احمدی',
+ fullName: 'مریم احمدی',
+ avatarUrl: '',
+ },
+ status: 'pending',
+ statusLabel: 'در انتظار پاسخ',
+ createdAt: '2026-05-08T09:15:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۱۸',
+ faCreatedTime: '۱۲:۴۵',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'سلام، درباره ساعت برگزاری جلسه چهارم سوال داشتم.',
+ time: '۱۲:۴۵',
+ },
+ ],
+ },
+ {
+ id: 403,
+ title: 'درخواست بستن تیکت',
+ user: {
+ id: 103,
+ firstName: 'علی',
+ lastName: 'علوی',
+ fullName: 'علی علوی',
+ avatarUrl: '',
+ },
+ status: 'closed',
+ statusLabel: 'بسته شده',
+ createdAt: '2026-05-07T14:10:00.000Z',
+ faCreatedAt: '۱۴۰۵/۰۲/۱۷',
+ faCreatedTime: '۱۷:۴۰',
+ messages: [
+ {
+ id: 1,
+ sender: 'user',
+ text: 'مشکل برطرف شد. لطفا تیکت بسته شود.',
+ time: '۱۷:۴۰',
+ },
+ {
+ id: 2,
+ sender: 'admin',
+ text: 'با تشکر از شما. تیکت بسته شد.',
+ time: '۱۷:۴۲',
+ },
+ ],
+ },
+]
diff --git a/src/services/mock/fixtures/admin-users.js b/src/services/mock/fixtures/admin-users.js
new file mode 100644
index 0000000..e3cdfce
--- /dev/null
+++ b/src/services/mock/fixtures/admin-users.js
@@ -0,0 +1,96 @@
+export const roles = [
+ { id: 1, name: 'admin' },
+ { id: 2, name: 'counselor' },
+ { id: 3, name: 'missionary' },
+ { id: 4, name: 'student' },
+ { id: 5, name: 'teacher' },
+]
+
+const provinces = [
+ { id: 1, name: 'تهران' },
+ { id: 2, name: 'اصفهان' },
+ { id: 3, name: 'فارس' },
+ { id: 4, name: 'خراسان رضوی' },
+]
+const cities = {
+ 1: [
+ { id: 11, name: 'تهران' },
+ { id: 12, name: 'شمیرانات' },
+ ],
+ 2: [{ id: 21, name: 'اصفهان' }],
+ 3: [{ id: 31, name: 'شیراز' }],
+ 4: [{ id: 41, name: 'مشهد' }],
+}
+const provinceById = (id) => provinces.find((p) => p.id === id) || provinces[0]
+const cityForProvince = (id) => cities[id]?.[0] || cities[1][0]
+
+const firstNames = [
+ 'فاطمه',
+ 'زهرا',
+ 'مریم',
+ 'علی',
+ 'حسین',
+ 'محمد',
+ 'سمیه',
+ 'نرگس',
+ 'حسن',
+ 'رضا',
+ 'مهدی',
+ 'الهام',
+ 'پروانه',
+ 'ساره',
+ 'مهسا',
+]
+const lastNames = [
+ 'رضایی',
+ 'محمدی',
+ 'حسینی',
+ 'احمدی',
+ 'جعفری',
+ 'علوی',
+ 'موسوی',
+ 'صالحی',
+ 'فاطمی',
+ 'کریمی',
+ 'تقوی',
+ 'مرادی',
+ 'هاشمی',
+ 'بهرامی',
+]
+
+const pick = (arr, i) => arr[i % arr.length]
+
+const makeUser = (i, overrides = {}) => {
+ const firstName = pick(firstNames, i)
+ const lastName = pick(lastNames, i + 3)
+ const province = provinceById((i % 4) + 1)
+ const city = cityForProvince(province.id)
+ const role = roles[(i % 4) + 1]?.name || 'student'
+ return {
+ id: 100 + i,
+ firstName,
+ lastName,
+ fullName: `${firstName} ${lastName}`,
+ phoneNumber: `0912${String(1_000_000 + i).padStart(7, '0')}`,
+ nationalCode: String(1_000_000_000 + i * 7).padStart(10, '0'),
+ avatarUrl: '',
+ status: i % 5 === 0 ? 'pending' : 'approved',
+ roles: [role],
+ roleId: roles.find((r) => r.name === role)?.id,
+ address: {
+ address: 'آدرس نمونه',
+ province,
+ city,
+ },
+ profile: {
+ bio: '',
+ birthDate: new Date(1990, i % 12, ((i * 3) % 27) + 1).toISOString(),
+ maritalStatus: i % 2 ? 'single' : 'married',
+ gender: i % 2 ? 'female' : 'male',
+ },
+ createdAt: new Date(Date.now() - i * 86_400_000).toISOString(),
+ ...overrides,
+ }
+}
+
+export const adminUsers = Array.from({ length: 24 }, (_, i) => makeUser(i))
diff --git a/src/services/mock/fixtures/common.js b/src/services/mock/fixtures/common.js
new file mode 100644
index 0000000..db873f7
--- /dev/null
+++ b/src/services/mock/fixtures/common.js
@@ -0,0 +1,47 @@
+export const provinces = [
+ { id: 1, name: 'تهران' },
+ { id: 2, name: 'اصفهان' },
+ { id: 3, name: 'فارس' },
+ { id: 4, name: 'خراسان رضوی' },
+ { id: 5, name: 'گیلان' },
+ { id: 6, name: 'مازندران' },
+ { id: 7, name: 'البرز' },
+ { id: 8, name: 'یزد' },
+]
+
+export const cities = {
+ 1: [
+ { id: 11, name: 'تهران' },
+ { id: 12, name: 'شمیرانات' },
+ { id: 13, name: 'ری' },
+ ],
+ 2: [
+ { id: 21, name: 'اصفهان' },
+ { id: 22, name: 'کاشان' },
+ { id: 23, name: 'نجفآباد' },
+ ],
+ 3: [
+ { id: 31, name: 'شیراز' },
+ { id: 32, name: 'مرودشت' },
+ ],
+ 4: [
+ { id: 41, name: 'مشهد' },
+ { id: 42, name: 'نیشابور' },
+ ],
+ 5: [
+ { id: 51, name: 'رشت' },
+ { id: 52, name: 'لاهیجان' },
+ ],
+ 6: [
+ { id: 61, name: 'ساری' },
+ { id: 62, name: 'بابل' },
+ ],
+ 7: [
+ { id: 71, name: 'کرج' },
+ { id: 72, name: 'نظرآباد' },
+ ],
+ 8: [
+ { id: 81, name: 'یزد' },
+ { id: 82, name: 'میبد' },
+ ],
+}
diff --git a/src/services/mock/fixtures/profile.js b/src/services/mock/fixtures/profile.js
new file mode 100644
index 0000000..3d054f4
--- /dev/null
+++ b/src/services/mock/fixtures/profile.js
@@ -0,0 +1,28 @@
+export const currentProfile = {
+ id: 1,
+ firstName: 'سجاد',
+ lastName: 'محمدی',
+ fullName: 'سجاد محمدی',
+ phoneNumber: '09123456789',
+ nationalCode: '0079827498',
+ avatarUrl: '',
+ status: 'approved',
+ roles: ['admin'],
+ address: {
+ address: 'خیابان آزادی، پلاک ۱۲',
+ province: { id: 1, name: 'تهران' },
+ city: { id: 11, name: 'تهران' },
+ },
+ profile: {
+ bio: 'مدیر سامانه و طلبه فعال در حوزه آموزش مجازی.',
+ birthDate: '1989-06-12T00:00:00.000Z',
+ maritalStatus: 'married',
+ gender: 'male',
+ educationStatus: 'graduate',
+ seminaryLevel: 'level_3',
+ universityLevel: 'master',
+ universityName: 'تهران',
+ fieldOfStudy: 'علوم قرآنی',
+ avatarId: null,
+ },
+}
diff --git a/src/services/mock/fixtures/student-courses.js b/src/services/mock/fixtures/student-courses.js
new file mode 100644
index 0000000..d5b73d5
--- /dev/null
+++ b/src/services/mock/fixtures/student-courses.js
@@ -0,0 +1,72 @@
+export const studentCourses = [
+ {
+ id: 11,
+ title: 'اصول اخلاق اسلامی - پاییز',
+ image: 'https://picsum.photos/seed/student1/200/200',
+ teacher: { firstName: 'علی', lastName: 'حسنی', fullName: 'علی حسنی' },
+ term: { id: 1, title: 'ترم پاییز ۱۴۰۴' },
+ startDate: '2025-09-23T00:00:00.000Z',
+ endDate: '2025-11-20T00:00:00.000Z',
+ status: 'watching',
+ averageScore: null,
+ sessions: [
+ {
+ id: 1001,
+ title: 'جلسه اول: مقدمه',
+ sessionTypeFa: 'حضوری',
+ durationMinutes: 90,
+ status: 'completed',
+ statusLabel: 'تکمیل شده',
+ },
+ {
+ id: 1002,
+ title: 'جلسه دوم: مبانی',
+ sessionTypeFa: 'حضوری',
+ durationMinutes: 90,
+ status: 'in_progress',
+ statusLabel: 'در حال بررسی',
+ },
+ {
+ id: 1003,
+ title: 'جلسه سوم: کاربردها',
+ sessionTypeFa: 'حضوری',
+ durationMinutes: 90,
+ status: 'locked',
+ statusLabel: 'قفل',
+ },
+ ],
+ },
+ {
+ id: 12,
+ title: 'مفاهیم قرآنی - پاییز',
+ image: 'https://picsum.photos/seed/student2/200/200',
+ teacher: { firstName: 'حسین', lastName: 'مرادی', fullName: 'حسین مرادی' },
+ term: { id: 1, title: 'ترم پاییز ۱۴۰۴' },
+ startDate: '2025-10-01T00:00:00.000Z',
+ endDate: '2025-12-15T00:00:00.000Z',
+ status: 'waitForExam',
+ averageScore: 17.5,
+ sessions: [
+ {
+ id: 1004,
+ title: 'تفسیر سوره حمد',
+ sessionTypeFa: 'آنلاین',
+ durationMinutes: 75,
+ status: 'completed',
+ statusLabel: 'تکمیل شده',
+ },
+ ],
+ },
+ {
+ id: 21,
+ title: 'مفاهیم قرآنی - بهار قبل',
+ image: '',
+ teacher: { firstName: 'حسین', lastName: 'مرادی', fullName: 'حسین مرادی' },
+ term: { id: 0, title: 'ترم بهار ۱۴۰۳' },
+ startDate: '2024-03-21T00:00:00.000Z',
+ endDate: '2024-06-21T00:00:00.000Z',
+ status: 'completed',
+ averageScore: 18.25,
+ sessions: [],
+ },
+]
diff --git a/src/services/mock/handlers.js b/src/services/mock/handlers.js
new file mode 100644
index 0000000..4a8d668
--- /dev/null
+++ b/src/services/mock/handlers.js
@@ -0,0 +1,71 @@
+import { camelize } from '@/utils/convert-to-camel-snake'
+import { findHandler } from '@/services/mock/registry'
+
+const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
+
+const stripUrl = (url) => (url ? url.split('?')[0] : '')
+
+const safeParse = (value) => {
+ try {
+ return camelize(JSON.parse(value))
+ } catch {
+ return value
+ }
+}
+
+const mockAdapter = async (config) => {
+ const url = stripUrl(config.url || '')
+ const method = (config.method || 'get').toUpperCase()
+ const match = findHandler(method, url)
+
+ if (!match) {
+ const err = new Error(`No mock registered for ${method} ${url}`)
+ err.response = {
+ status: 404,
+ statusText: 'Not Mocked',
+ data: { message: err.message },
+ }
+ err.config = config
+ throw err
+ }
+
+ await sleep(150)
+
+ const query = config.params ? camelize(config.params) : {}
+ let data = config.data
+ if (data instanceof FormData) {
+ /* leave as-is */
+ } else if (typeof data === 'string') {
+ data = safeParse(data)
+ } else if (data) {
+ data = camelize(data)
+ }
+
+ const result = await match.entry.handler({
+ method,
+ url,
+ params: match.params,
+ query,
+ data,
+ headers: config.headers,
+ })
+
+ return {
+ data: result,
+ status: 200,
+ statusText: 'OK',
+ headers: {},
+ config,
+ }
+}
+
+export const isMocksEnabled = () => import.meta.env.VITE_USE_MOCKS === 'true'
+
+import.meta.glob('@/services/mock/routes/*.js', { eager: true })
+
+export const setupMocks = (instance) => {
+ if (!isMocksEnabled()) return
+ instance.defaults.adapter = mockAdapter
+}
+
+export { register } from '@/services/mock/registry'
diff --git a/src/services/mock/helpers.js b/src/services/mock/helpers.js
new file mode 100644
index 0000000..9bf32fc
--- /dev/null
+++ b/src/services/mock/helpers.js
@@ -0,0 +1,91 @@
+export const ok = (data, meta) => ({ data, meta })
+
+export const paginate = (items, query) => {
+ const page = Number(query.page || 1)
+ const perPage = Number(query.perPage || 10)
+ const total = items.length
+ const lastPage = Math.max(1, Math.ceil(total / perPage))
+ const start = (page - 1) * perPage
+ const sliced = items.slice(start, start + perPage)
+ return {
+ data: sliced,
+ meta: { page, perPage, total, lastPage, currentPage: page },
+ }
+}
+
+const stringIncludes = (haystack, needle) =>
+ String(haystack ?? '')
+ .toLowerCase()
+ .includes(String(needle ?? '').toLowerCase())
+
+export const filterItems = (items, query, rules = {}) =>
+ items.filter((item) => {
+ for (const [key, rule] of Object.entries(rules)) {
+ const value = query[key]
+ if (value === '' || value == null) continue
+ if (typeof rule === 'function') {
+ if (!rule(item, value)) return false
+ } else
+ switch (rule) {
+ case 'eq': {
+ if (String(item[key]) !== String(value)) return false
+
+ break
+ }
+ case 'includes': {
+ if (!stringIncludes(item[key], value)) return false
+
+ break
+ }
+ case 'fromDate': {
+ if (!item[rule.field || 'createdAt']) continue
+ if (new Date(item[rule.field || 'createdAt']) < new Date(value)) return false
+
+ break
+ }
+ // No default
+ }
+ }
+ return true
+ })
+
+export const filterDateRange = (items, query, field = 'createdAt') => {
+ if (!query.fromDate && !query.toDate) return items
+ return items.filter((item) => {
+ const v = item[field]
+ if (!v) return !query.fromDate && !query.toDate
+ const d = new Date(v).getTime()
+ if (query.fromDate && d < new Date(query.fromDate).getTime()) return false
+ if (query.toDate && d > new Date(query.toDate).getTime()) return false
+ return true
+ })
+}
+
+let nextId = 1000
+export const makeId = () => ++nextId
+
+export const findOrThrow = (list, id) => {
+ const found = list.find((item) => String(item.id) === String(id))
+ if (!found) {
+ const err = new Error('Not Found')
+ err.response = { status: 404, statusText: 'Not Found', data: { message: 'Not Found' } }
+ throw err
+ }
+ return found
+}
+
+export const removeById = (list, id) => {
+ const idx = list.findIndex((x) => String(x.id) === String(id))
+ if (idx !== -1) list.splice(idx, 1)
+}
+
+export const updateById = (list, id, patch) => {
+ const idx = list.findIndex((x) => String(x.id) === String(id))
+ if (idx === -1) return null
+ list[idx] = { ...list[idx], ...patch }
+ return list[idx]
+}
+
+export const isoDaysFromNow = (days) => new Date(Date.now() + days * 86_400_000).toISOString()
+
+export const isoNow = () => new Date().toISOString()
diff --git a/src/services/mock/index.js b/src/services/mock/index.js
new file mode 100644
index 0000000..112303c
--- /dev/null
+++ b/src/services/mock/index.js
@@ -0,0 +1 @@
+export { register, setupMocks, isMocksEnabled } from '@/services/mock/handlers'
diff --git a/src/services/mock/registry.js b/src/services/mock/registry.js
new file mode 100644
index 0000000..90f0b5a
--- /dev/null
+++ b/src/services/mock/registry.js
@@ -0,0 +1,27 @@
+const handlers = []
+
+export const register = (method, urlPattern, handler) => {
+ const paramNames = []
+ const regexSource = urlPattern.replace(/:([A-Za-z][\dA-Za-z]*)/g, (_, name) => {
+ paramNames.push(name)
+ return '([^/]+)'
+ })
+ const regex = new RegExp(`^${regexSource}$`)
+ handlers.push({ method: method.toUpperCase(), regex, paramNames, handler })
+}
+
+export const findHandler = (method, url) => {
+ const upper = method.toUpperCase()
+ for (const entry of handlers) {
+ if (entry.method !== upper) continue
+ const match = entry.regex.exec(url)
+ if (match) {
+ const params = {}
+ entry.paramNames.forEach((name, i) => {
+ params[name] = decodeURIComponent(match[i + 1])
+ })
+ return { entry, params }
+ }
+ }
+ return null
+}
diff --git a/src/services/mock/routes/admin-assignments.js b/src/services/mock/routes/admin-assignments.js
new file mode 100644
index 0000000..596ad32
--- /dev/null
+++ b/src/services/mock/routes/admin-assignments.js
@@ -0,0 +1,107 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminAssignments, assignmentSubmissions } from '@/services/mock/fixtures/admin-assignments'
+import { adminCourseTemplates } from '@/services/mock/fixtures/admin-courses'
+import { adminSessions } from '@/services/mock/fixtures/admin-sessions'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+const computeDurationDays = (start, end) => {
+ if (!start || !end) return null
+ const diff = Math.ceil((new Date(end).getTime() - new Date(start).getTime()) / 86_400_000)
+ return diff >= 0 ? diff : null
+}
+
+register('GET', endpoints.getAssignmentsList, ({ query }) => {
+ let list = filterItems(adminAssignments, query, {
+ title: 'includes',
+ courseTemplateId: (item, v) => String(item.courseTemplate?.id) === String(v),
+ sessionId: (item, v) => String(item.session?.id) === String(v),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showAssignment, ({ params }) => ({
+ data: findOrThrow(adminAssignments, params.id),
+}))
+
+register('POST', endpoints.addNewAssignment, ({ data }) => {
+ const tpl = adminCourseTemplates.find((c) => c.id === Number(data.courseTemplateId))
+ const sess = adminSessions.find((s) => s.id === Number(data.sessionId))
+ const item = {
+ id: makeId(),
+ title: data.title || '',
+ description: data.description || '',
+ courseTemplate: tpl ? { id: tpl.id, title: tpl.title } : null,
+ courseTemplateTitle: tpl?.title || '',
+ session: sess ? { id: sess.id, title: sess.title } : null,
+ sessionTitle: sess?.title || '',
+ startDate: data.startDate || '',
+ endDate: data.endDate || '',
+ durationDays: computeDurationDays(data.startDate, data.endDate),
+ priority: data.priority || 'mandatory',
+ submissionsCount: 0,
+ attachments: data.attachments || [],
+ createdAt: isoNow(),
+ }
+ adminAssignments.unshift(item)
+ return { data: item }
+})
+
+register('PUT', endpoints.updateAssignment, ({ params, data }) => {
+ const tpl = adminCourseTemplates.find((c) => c.id === Number(data.courseTemplateId))
+ const sess = adminSessions.find((s) => s.id === Number(data.sessionId))
+ return {
+ data: updateById(adminAssignments, params.id, {
+ title: data.title,
+ description: data.description,
+ courseTemplate: tpl ? { id: tpl.id, title: tpl.title } : undefined,
+ courseTemplateTitle: tpl?.title,
+ session: sess ? { id: sess.id, title: sess.title } : undefined,
+ sessionTitle: sess?.title,
+ startDate: data.startDate,
+ endDate: data.endDate,
+ durationDays: computeDurationDays(data.startDate, data.endDate),
+ priority: data.priority,
+ attachments: data.attachments || [],
+ }),
+ }
+})
+
+register('DELETE', endpoints.deleteAssignment, ({ params }) => {
+ removeById(adminAssignments, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('GET', endpoints.getAssignmentSubmissions, ({ params, query }) => {
+ const list = assignmentSubmissions.get(Number(params.assignmentId)) || []
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showAssignmentSubmission, ({ params }) => {
+ const list = assignmentSubmissions.get(Number(params.assignmentId)) || []
+ const found = list.find((s) => String(s.id) === String(params.submissionId))
+ return { data: found || null }
+})
+
+register('POST', endpoints.reviewAssignmentSubmission, ({ params, data }) => {
+ const list = assignmentSubmissions.get(Number(params.assignmentId)) || []
+ const sub = list.find((s) => String(s.id) === String(params.submissionId))
+ if (sub) {
+ Object.assign(sub, {
+ score: data.score ?? sub.score,
+ status: data.status ?? sub.status,
+ reviewerNote: data.reviewerNote ?? sub.reviewerNote,
+ })
+ }
+ return { data: sub || null }
+})
diff --git a/src/services/mock/routes/admin-consultations.js b/src/services/mock/routes/admin-consultations.js
new file mode 100644
index 0000000..99db986
--- /dev/null
+++ b/src/services/mock/routes/admin-consultations.js
@@ -0,0 +1,56 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminConsultations } from '@/services/mock/fixtures/admin-consultations'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ updateById,
+} from '@/services/mock/helpers'
+
+const STATUS_LABELS = {
+ in_progress: 'در حال گفتگو',
+ answered: 'پاسخ داده شده',
+ closed: 'بسته شده',
+}
+
+register('GET', endpoints.getConsultationsList, ({ query }) => {
+ let list = filterItems(adminConsultations, query, {
+ status: 'eq',
+ userName: (item, v) =>
+ `${item.user?.firstName || ''} ${item.user?.lastName || ''}`
+ .toLowerCase()
+ .includes(String(v).toLowerCase()),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showConsultation, ({ params }) => ({
+ data: findOrThrow(adminConsultations, params.id),
+}))
+
+register('POST', endpoints.sendConsultationMessage, ({ params, data }) => {
+ const consultation = findOrThrow(adminConsultations, params.id)
+ const message = {
+ id: makeId(),
+ sender: 'admin',
+ text: data.text || '',
+ time: 'همین الان',
+ sentAt: isoNow(),
+ }
+ consultation.messages = [...(consultation.messages || []), message]
+ consultation.status = 'answered'
+ consultation.statusLabel = STATUS_LABELS.answered
+ return { data: consultation }
+})
+
+register('POST', endpoints.changeConsultationStatus, ({ params, data }) => ({
+ data: updateById(adminConsultations, params.id, {
+ status: data.status,
+ statusLabel: STATUS_LABELS[data.status] || data.status,
+ }),
+}))
diff --git a/src/services/mock/routes/admin-courses.js b/src/services/mock/routes/admin-courses.js
new file mode 100644
index 0000000..22b3cbf
--- /dev/null
+++ b/src/services/mock/routes/admin-courses.js
@@ -0,0 +1,166 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminCourseTemplates, adminOfferedCourses } from '@/services/mock/fixtures/admin-courses'
+import { adminTerms } from '@/services/mock/fixtures/admin-terms'
+import { adminUsers } from '@/services/mock/fixtures/admin-users'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getCourseTemplatesList, ({ query }) => {
+ let list = filterItems(adminCourseTemplates, query, {
+ title: 'includes',
+ status: (item, v) => String(item.isActiveByDefault ? 1 : 0) === String(v),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showCourseTemplate, ({ params }) => ({
+ data: findOrThrow(adminCourseTemplates, params.id),
+}))
+
+register('POST', endpoints.addNewCourseTemplate, ({ data }) => {
+ const teacher = adminUsers.find((u) => u.id === Number(data.defaultTeacherId))
+ const item = {
+ id: makeId(),
+ title: data.title || '',
+ description: data.description || '',
+ image: data.imageId ? `https://picsum.photos/seed/course-${data.imageId}/200/200` : '',
+ defaultTeacher: teacher
+ ? {
+ id: teacher.id,
+ firstName: teacher.firstName,
+ lastName: teacher.lastName,
+ fullName: `${teacher.firstName} ${teacher.lastName}`,
+ }
+ : null,
+ defaultCapacity: Number(data.defaultCapacity) || 0,
+ isActiveByDefault: !!data.isActiveByDefault,
+ prerequisitesCount: (data.prerequisites || []).length,
+ prerequisites: (data.prerequisites || []).map((id) => ({
+ courseId: id,
+ course: adminCourseTemplates.find((c) => c.id === Number(id)) || { id },
+ })),
+ createdAt: isoNow(),
+ }
+ adminCourseTemplates.unshift(item)
+ return { data: item }
+})
+
+register('PUT', endpoints.updateCourseTemplate, ({ params, data }) => {
+ const teacher = adminUsers.find((u) => u.id === Number(data.defaultTeacherId))
+ return {
+ data: updateById(adminCourseTemplates, params.id, {
+ title: data.title,
+ description: data.description,
+ image: data.imageId ? `https://picsum.photos/seed/course-${data.imageId}/200/200` : undefined,
+ defaultTeacher: teacher
+ ? {
+ id: teacher.id,
+ firstName: teacher.firstName,
+ lastName: teacher.lastName,
+ fullName: `${teacher.firstName} ${teacher.lastName}`,
+ }
+ : undefined,
+ defaultCapacity: Number(data.defaultCapacity) || 0,
+ isActiveByDefault: !!data.isActiveByDefault,
+ prerequisites: (data.prerequisites || []).map((id) => ({
+ courseId: id,
+ course: adminCourseTemplates.find((c) => c.id === Number(id)) || { id },
+ })),
+ prerequisitesCount: (data.prerequisites || []).length,
+ }),
+ }
+})
+
+register('DELETE', endpoints.deleteCourseTemplate, ({ params }) => {
+ removeById(adminCourseTemplates, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('POST', endpoints.changeStatusCourseTemplate, ({ params, data }) => ({
+ data: updateById(adminCourseTemplates, params.id, {
+ isActiveByDefault: !!data.isActiveByDefault,
+ }),
+}))
+
+register('GET', endpoints.getCoursesList, ({ query }) => {
+ let list = filterItems(adminOfferedCourses, query, {
+ title: 'includes',
+ termId: 'eq',
+ status: (item, v) => String(item.isActive ? 1 : 0) === String(v),
+ })
+ list = filterDateRange(list, query, 'startDate')
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showCourse, ({ params }) => ({
+ data: findOrThrow(adminOfferedCourses, params.id),
+}))
+
+register('POST', endpoints.addNewCourse, ({ data }) => {
+ const template = adminCourseTemplates.find((t) => t.id === Number(data.templateId))
+ const term = adminTerms.find((t) => t.id === Number(data.termId))
+ const teacher = adminUsers.find((u) => u.id === Number(data.teacherId))
+ const item = {
+ id: makeId(),
+ title: data.title || template?.title || '',
+ image: data.imageId ? `https://picsum.photos/seed/offered-${data.imageId}/200/200` : '',
+ template: template ? { id: template.id, title: template.title } : null,
+ templateId: template?.id,
+ term: term ? { id: term.id, title: term.title } : null,
+ termId: term?.id,
+ teacher: teacher
+ ? {
+ id: teacher.id,
+ firstName: teacher.firstName,
+ lastName: teacher.lastName,
+ fullName: `${teacher.firstName} ${teacher.lastName}`,
+ }
+ : null,
+ capacity: Number(data.capacity) || 0,
+ isActive: !!data.isActive,
+ prerequisitesCount: 0,
+ startDate: term?.startDate || '',
+ endDate: term?.endDate || '',
+ createdAt: isoNow(),
+ }
+ adminOfferedCourses.unshift(item)
+ return { data: item }
+})
+
+register('PUT', endpoints.updateCourse, ({ params, data }) => {
+ const template = adminCourseTemplates.find((t) => t.id === Number(data.templateId))
+ const term = adminTerms.find((t) => t.id === Number(data.termId))
+ return {
+ data: updateById(adminOfferedCourses, params.id, {
+ title: data.title,
+ image: data.imageId
+ ? `https://picsum.photos/seed/offered-${data.imageId}/200/200`
+ : undefined,
+ template: template ? { id: template.id, title: template.title } : undefined,
+ templateId: template?.id,
+ term: term ? { id: term.id, title: term.title } : undefined,
+ termId: term?.id,
+ capacity: Number(data.capacity) || 0,
+ isActive: !!data.isActive,
+ }),
+ }
+})
+
+register('DELETE', endpoints.deleteCourse, ({ params }) => {
+ removeById(adminOfferedCourses, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('POST', endpoints.changeStatusCourse, ({ params, data }) => ({
+ data: updateById(adminOfferedCourses, params.id, { isActive: !!data.isActive }),
+}))
diff --git a/src/services/mock/routes/admin-exams.js b/src/services/mock/routes/admin-exams.js
new file mode 100644
index 0000000..b48a01c
--- /dev/null
+++ b/src/services/mock/routes/admin-exams.js
@@ -0,0 +1,94 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminExams, examParticipants } from '@/services/mock/fixtures/admin-exams'
+import { adminCourseTemplates } from '@/services/mock/fixtures/admin-courses'
+import { adminSessions } from '@/services/mock/fixtures/admin-sessions'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getExamsList, ({ query }) => {
+ let list = filterItems(adminExams, query, {
+ title: 'includes',
+ courseTemplateId: (item, v) => String(item.courseTemplate?.id) === String(v),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showExam, ({ params }) => ({
+ data: findOrThrow(adminExams, params.id),
+}))
+
+register('POST', endpoints.addNewExam, ({ data }) => {
+ const session = adminSessions.find((s) => s.id === Number(data.sessionId))
+ const template = session?.courseTemplate
+ ? adminCourseTemplates.find((c) => c.id === Number(session.courseTemplate.id))
+ : null
+ const item = {
+ id: makeId(),
+ title: data.title || '',
+ description: data.description || '',
+ session: session ? { id: session.id, title: session.title } : null,
+ sessionTitle: session?.title || '',
+ courseTemplate: template ? { id: template.id, title: template.title } : null,
+ courseTemplateTitle: template?.title || '',
+ durationMinutes: Number(data.durationMinutes) || 0,
+ passingScore: Number(data.passingScore) || 0,
+ questionsCount: data.questions?.length || 0,
+ randomize: !!data.randomize,
+ endDate: data.endDate || '',
+ startDate: isoNow(),
+ createdAt: isoNow(),
+ questions: data.questions || [],
+ usedInTerms: [],
+ }
+ adminExams.unshift(item)
+ return { data: item }
+})
+
+register('PUT', endpoints.updateExam, ({ params, data }) => {
+ const session = adminSessions.find((s) => s.id === Number(data.sessionId))
+ const template = session?.courseTemplate
+ ? adminCourseTemplates.find((c) => c.id === Number(session.courseTemplate.id))
+ : null
+ return {
+ data: updateById(adminExams, params.id, {
+ title: data.title,
+ description: data.description,
+ session: session ? { id: session.id, title: session.title } : undefined,
+ sessionTitle: session?.title,
+ courseTemplate: template ? { id: template.id, title: template.title } : undefined,
+ courseTemplateTitle: template?.title,
+ durationMinutes: Number(data.durationMinutes) || 0,
+ passingScore: Number(data.passingScore) || 0,
+ questionsCount: data.questions?.length || 0,
+ randomize: !!data.randomize,
+ endDate: data.endDate,
+ questions: data.questions || [],
+ }),
+ }
+})
+
+register('DELETE', endpoints.deleteExam, ({ params }) => {
+ removeById(adminExams, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('GET', endpoints.getExamParticipants, ({ params, query }) => {
+ const list = examParticipants.get(Number(params.examId)) || []
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showExamParticipant, ({ params }) => {
+ const list = examParticipants.get(Number(params.examId)) || []
+ const found = list.find((p) => String(p.id) === String(params.participantId))
+ return { data: found || null }
+})
diff --git a/src/services/mock/routes/admin-pending-students.js b/src/services/mock/routes/admin-pending-students.js
new file mode 100644
index 0000000..0bb4e0e
--- /dev/null
+++ b/src/services/mock/routes/admin-pending-students.js
@@ -0,0 +1,49 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { pendingStudents } from '@/services/mock/fixtures/admin-pending-students'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getPendingStudents, ({ query }) => {
+ let list = filterItems(pendingStudents, query, {
+ name: (item, v) =>
+ `${item.firstName} ${item.lastName}`.toLowerCase().includes(String(v).toLowerCase()),
+ nationalCode: 'includes',
+ })
+ list = filterDateRange(list, query, 'submittedAt')
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showPendingStudent, ({ params }) => ({
+ data: findOrThrow(pendingStudents, params.id),
+}))
+
+register('POST', endpoints.changeStatusPendingStudent, ({ params, data }) => {
+ const target = findOrThrow(pendingStudents, params.id)
+ const patch = {
+ status: data.status,
+ verification: {
+ ...target.verification,
+ status: data.status,
+ rejectionReason: data.rejectionReason || '',
+ adminNote: data.adminNote || '',
+ },
+ }
+ updateById(pendingStudents, params.id, patch)
+ if (data.status === 'approved') {
+ removeById(pendingStudents, params.id)
+ }
+ return { data: { user: { ...target, ...patch } } }
+})
+
+register('GET', endpoints.downloadPdfPendingStudentInfo, ({ params }) => ({
+ data: {
+ downloadUrl: `https://example.com/mock-pdf-${params.id}.pdf`,
+ },
+}))
diff --git a/src/services/mock/routes/admin-sessions.js b/src/services/mock/routes/admin-sessions.js
new file mode 100644
index 0000000..682e40d
--- /dev/null
+++ b/src/services/mock/routes/admin-sessions.js
@@ -0,0 +1,86 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminSessions, sessionAttendance } from '@/services/mock/fixtures/admin-sessions'
+import { adminCourseTemplates } from '@/services/mock/fixtures/admin-courses'
+import { SESSION_TYPE } from '@/enums'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+const enrich = (session) => ({
+ ...session,
+ sessionTypeFa: SESSION_TYPE[session.sessionType] || session.sessionTypeFa || '',
+})
+
+register('GET', endpoints.getSessionsList, ({ query }) => {
+ let list = filterItems(adminSessions, query, {
+ title: 'includes',
+ courseTemplateId: (item, v) => String(item.courseTemplate?.id) === String(v),
+ sessionType: 'eq',
+ })
+ list = filterDateRange(list, query)
+ // eslint-disable-next-line unicorn/no-array-callback-reference
+ return paginate(list.map(enrich), query)
+})
+
+register('GET', endpoints.showSession, ({ params }) => ({
+ data: enrich(findOrThrow(adminSessions, params.id)),
+}))
+
+register('POST', endpoints.addNewSession, ({ data }) => {
+ const tpl = adminCourseTemplates.find((c) => c.id === Number(data.courseTemplateId))
+ const item = {
+ id: makeId(),
+ title: data.title || '',
+ description: data.description || '',
+ image: data.imageId ? `https://picsum.photos/seed/session-${data.imageId}/200/200` : '',
+ courseTemplate: tpl ? { id: tpl.id, title: tpl.title } : null,
+ sessionType: data.sessionType || 'in_person',
+ durationMinutes: Number(data.durationMinutes) || 0,
+ order: Number(data.order) || 1,
+ sessionConfig: data.sessionConfig || {},
+ materials: data.materials || [],
+ usedInTerms: [],
+ createdAt: isoNow(),
+ }
+ adminSessions.unshift(item)
+ return { data: enrich(item) }
+})
+
+register('PUT', endpoints.updateSession, ({ params, data }) => {
+ const tpl = adminCourseTemplates.find((c) => c.id === Number(data.courseTemplateId))
+ const updated = updateById(adminSessions, params.id, {
+ title: data.title,
+ description: data.description,
+ image: data.imageId ? `https://picsum.photos/seed/session-${data.imageId}/200/200` : undefined,
+ courseTemplate: tpl ? { id: tpl.id, title: tpl.title } : undefined,
+ sessionType: data.sessionType,
+ durationMinutes: Number(data.durationMinutes) || 0,
+ order: Number(data.order) || 1,
+ sessionConfig: data.sessionConfig ?? undefined,
+ materials: data.materials ?? undefined,
+ })
+ return { data: enrich(updated) }
+})
+
+register('DELETE', endpoints.deleteSession, ({ params }) => {
+ removeById(adminSessions, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('POST', endpoints.changeStatusSession, ({ params, data }) => {
+ const updated = updateById(adminSessions, params.id, { isActive: !!data.isActive })
+ return { data: enrich(updated) }
+})
+
+register('GET', endpoints.getSessionsAttendance, ({ params, query }) => {
+ const list = sessionAttendance.get(Number(params.sessionId)) || []
+ return paginate(list, query)
+})
diff --git a/src/services/mock/routes/admin-terms.js b/src/services/mock/routes/admin-terms.js
new file mode 100644
index 0000000..cb1f86f
--- /dev/null
+++ b/src/services/mock/routes/admin-terms.js
@@ -0,0 +1,153 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminTerms, termStudentLinks } from '@/services/mock/fixtures/admin-terms'
+import { adminUsers } from '@/services/mock/fixtures/admin-users'
+import { adminOfferedCourses } from '@/services/mock/fixtures/admin-courses'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getTermsList, ({ query }) => {
+ let list = filterItems(adminTerms, query, {
+ title: 'includes',
+ status: (item, v) => String(item.isActive ? 1 : 0) === String(v),
+ })
+ list = filterDateRange(list, query, 'startDate')
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showTerm, ({ params }) => ({
+ data: findOrThrow(adminTerms, params.id),
+}))
+
+register('POST', endpoints.addNewTerm, ({ data }) => {
+ const term = {
+ id: makeId(),
+ title: data.title || '',
+ description: data.description || '',
+ image: data.imageId ? `https://picsum.photos/seed/term-${data.imageId}/200/200` : '',
+ startDate: data.startDate || '',
+ endDate: data.endDate || '',
+ isActive: true,
+ studentsCount: 0,
+ coursesCount: 0,
+ createdAt: isoNow(),
+ }
+ adminTerms.unshift(term)
+ return { data: term }
+})
+
+register('PUT', endpoints.updateTerm, ({ params, data }) => ({
+ data: updateById(adminTerms, params.id, {
+ title: data.title,
+ description: data.description,
+ startDate: data.startDate,
+ endDate: data.endDate,
+ image: data.imageId ? `https://picsum.photos/seed/term-${data.imageId}/200/200` : undefined,
+ }),
+}))
+
+register('DELETE', endpoints.deleteTerm, ({ params }) => {
+ removeById(adminTerms, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('POST', endpoints.cloneTerm, ({ params }) => {
+ const src = findOrThrow(adminTerms, params.id)
+ const clone = { ...src, id: makeId(), title: `${src.title} (کپی)`, createdAt: isoNow() }
+ adminTerms.unshift(clone)
+ return { data: clone }
+})
+
+register('POST', endpoints.changeStatusTerm, ({ params, data }) => ({
+ data: updateById(adminTerms, params.id, { isActive: !!data.isActive }),
+}))
+
+const studentSnapshot = (link) => {
+ const user = adminUsers.find((u) => u.id === link.userId)
+ return user ? { ...user, isOnLeave: link.isOnLeave } : null
+}
+
+register('GET', endpoints.listUserTerm, ({ params, query }) => {
+ const links = termStudentLinks.get(Number(params.termId)) || []
+ const list = links.map((element) => studentSnapshot(element)).filter(Boolean)
+ return paginate(list, query)
+})
+
+register('POST', endpoints.addUserTerm, ({ params, data }) => {
+ const termId = Number(params.termId)
+ const links = termStudentLinks.get(termId) || []
+ const ids = Array.isArray(data.userIds) ? data.userIds : []
+ ids.forEach((userId) => {
+ if (!links.some((l) => l.userId === Number(userId))) {
+ links.push({ userId: Number(userId), isOnLeave: false })
+ }
+ })
+ termStudentLinks.set(termId, links)
+ const added = ids
+ .map((id) => adminUsers.find((u) => u.id === Number(id)))
+ .filter(Boolean)
+ .map((u) => ({ ...u, isOnLeave: false }))
+ const term = adminTerms.find((t) => t.id === termId)
+ if (term) term.studentsCount = links.length
+ return { data: added }
+})
+
+register('DELETE', endpoints.removeUserTerm, ({ params }) => {
+ const termId = Number(params.termId)
+ const links = termStudentLinks.get(termId) || []
+ const idx = links.findIndex((l) => String(l.userId) === String(params.userId))
+ if (idx !== -1) links.splice(idx, 1)
+ termStudentLinks.set(termId, links)
+ const term = adminTerms.find((t) => t.id === termId)
+ if (term) term.studentsCount = links.length
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('POST', endpoints.changeLeaveStatus, ({ params, data }) => {
+ const termId = Number(params.termId)
+ const links = termStudentLinks.get(termId) || []
+ const link = links.find((l) => String(l.userId) === String(params.userId))
+ if (link) link.isOnLeave = !!data.setLeave
+ return { data: { isOnLeave: !!data.setLeave } }
+})
+
+register('GET', endpoints.listCourseTerm, ({ params, query }) => {
+ const termId = Number(params.termId)
+ const list = adminOfferedCourses.filter((c) => Number(c.termId) === termId)
+ return paginate(list, query)
+})
+
+register('POST', endpoints.addCourseTerm, ({ params, data }) => {
+ const termId = Number(params.termId)
+ const ids = Array.isArray(data.courseIds) ? data.courseIds : []
+ const linked = []
+ ids.forEach((id) => {
+ const course = adminOfferedCourses.find((c) => Number(c.id) === Number(id))
+ if (course) {
+ course.termId = termId
+ course.term = adminTerms.some((t) => t.id === termId)
+ ? { id: termId, title: adminTerms.find((t) => t.id === termId).title }
+ : course.term
+ linked.push(course)
+ }
+ })
+ return { data: linked }
+})
+
+register('DELETE', endpoints.removeCourseTerm, ({ params }) => {
+ const courseId = Number(params.courseId)
+ const course = adminOfferedCourses.find((c) => c.id === courseId)
+ if (course) {
+ course.termId = null
+ course.term = null
+ }
+ return { data: { message: 'حذف موفق' } }
+})
diff --git a/src/services/mock/routes/admin-tickets.js b/src/services/mock/routes/admin-tickets.js
new file mode 100644
index 0000000..f41099e
--- /dev/null
+++ b/src/services/mock/routes/admin-tickets.js
@@ -0,0 +1,55 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminTickets } from '@/services/mock/fixtures/admin-tickets'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getTicketsList, ({ query }) => {
+ let list = filterItems(adminTickets, query, {
+ status: 'eq',
+ userName: (item, v) =>
+ `${item.user?.firstName || ''} ${item.user?.lastName || ''}`
+ .toLowerCase()
+ .includes(String(v).toLowerCase()),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showTicket, ({ params }) => ({
+ data: findOrThrow(adminTickets, params.id),
+}))
+
+register('POST', endpoints.sendTicketMessage, ({ params, data }) => {
+ const ticket = findOrThrow(adminTickets, params.id)
+ const message = {
+ id: makeId(),
+ sender: 'admin',
+ text: data.text || '',
+ time: 'همین الان',
+ sentAt: isoNow(),
+ }
+ ticket.messages = [...(ticket.messages || []), message]
+ ticket.status = 'answered'
+ ticket.statusLabel = 'پاسخ داده شده'
+ return { data: ticket }
+})
+
+register('POST', endpoints.changeTicketStatus, ({ params, data }) => ({
+ data: updateById(adminTickets, params.id, {
+ status: data.status,
+ statusLabel:
+ data.status === 'closed'
+ ? 'بسته شده'
+ : data.status === 'answered'
+ ? 'پاسخ داده شده'
+ : 'در انتظار پاسخ',
+ }),
+}))
diff --git a/src/services/mock/routes/admin-users.js b/src/services/mock/routes/admin-users.js
new file mode 100644
index 0000000..de97124
--- /dev/null
+++ b/src/services/mock/routes/admin-users.js
@@ -0,0 +1,103 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { adminUsers, roles } from '@/services/mock/fixtures/admin-users'
+import {
+ filterDateRange,
+ filterItems,
+ findOrThrow,
+ isoNow,
+ makeId,
+ paginate,
+ removeById,
+ updateById,
+} from '@/services/mock/helpers'
+
+register('GET', endpoints.getApprovedUsers, ({ query }) => {
+ let list = filterItems(adminUsers, query, {
+ name: (item, v) =>
+ `${item.firstName} ${item.lastName}`.toLowerCase().includes(String(v).toLowerCase()),
+ nationalCode: 'includes',
+ phoneNumber: 'includes',
+ roleId: (item, v) => String(item.roleId) === String(v),
+ })
+ list = filterDateRange(list, query)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showUserDetails, ({ params }) => ({
+ data: findOrThrow(adminUsers, params.id),
+}))
+
+register('POST', endpoints.addNewUser, ({ data }) => {
+ const id = makeId()
+ const role = roles.find((r) => r.id === Number(data.roleId)) || null
+ const province = data.provinceId ? { id: data.provinceId, name: '' } : null
+ const city = data.cityId ? { id: data.cityId, name: '' } : null
+ const user = {
+ id,
+ firstName: data.firstName || '',
+ lastName: data.lastName || '',
+ fullName: `${data.firstName || ''} ${data.lastName || ''}`.trim(),
+ phoneNumber: data.phoneNumber || '',
+ nationalCode: data.nationalCode || '',
+ avatarUrl: '',
+ status: 'approved',
+ roles: role ? [role.name] : [],
+ roleId: role?.id,
+ address: { address: data.address || '', province, city },
+ profile: {
+ bio: data.bio || '',
+ birthDate: data.birthDate || '',
+ maritalStatus: data.maritalStatus || '',
+ gender: data.gender || '',
+ avatarId: data.avatarId || null,
+ },
+ createdAt: isoNow(),
+ }
+ adminUsers.unshift(user)
+ return { data: user }
+})
+
+register('PUT', endpoints.updateUser, ({ params, data }) => {
+ const role = roles.find((r) => r.id === Number(data.roleId))
+ const patch = {
+ firstName: data.firstName,
+ lastName: data.lastName,
+ fullName: `${data.firstName || ''} ${data.lastName || ''}`.trim(),
+ phoneNumber: data.phoneNumber,
+ nationalCode: data.nationalCode,
+ roleId: role?.id,
+ roles: role ? [role.name] : [],
+ address: {
+ address: data.address || '',
+ province: data.provinceId ? { id: data.provinceId, name: '' } : null,
+ city: data.cityId ? { id: data.cityId, name: '' } : null,
+ },
+ profile: {
+ bio: data.bio || '',
+ birthDate: data.birthDate || '',
+ maritalStatus: data.maritalStatus || '',
+ gender: data.gender || '',
+ avatarId: data.avatarId || null,
+ },
+ }
+ const updated = updateById(adminUsers, params.id, patch)
+ return { data: updated }
+})
+
+register('POST', endpoints.updateUserRole, ({ params, data }) => {
+ const role = roles.find((r) => r.id === Number(data.roleId))
+ const patch = role ? { roleId: role.id, roles: [role.name] } : {}
+ return { data: updateById(adminUsers, params.id, patch) }
+})
+
+register('POST', endpoints.changeUserStatus, ({ params, data }) => ({
+ data: updateById(adminUsers, params.id, { status: data.status }),
+}))
+
+register('DELETE', endpoints.deleteUser, ({ params }) => {
+ removeById(adminUsers, params.id)
+ return { data: { message: 'حذف موفق' } }
+})
+
+register('GET', endpoints.getRolesList, () => ({ data: roles }))
diff --git a/src/services/mock/routes/auth.js b/src/services/mock/routes/auth.js
new file mode 100644
index 0000000..3d49e32
--- /dev/null
+++ b/src/services/mock/routes/auth.js
@@ -0,0 +1,89 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { currentProfile } from '@/services/mock/fixtures/profile'
+import { makeId } from '@/services/mock/helpers'
+
+const fakeToken = 'mock-token-1234567890'
+
+register('POST', endpoints.login, () => ({
+ data: { user: currentProfile, token: fakeToken },
+}))
+
+register('POST', endpoints.loginWithCode2Step, () => ({
+ data: { user: currentProfile, token: fakeToken },
+}))
+
+register('POST', endpoints.verifyCode, () => ({
+ data: { user: currentProfile, token: fakeToken },
+}))
+
+register('POST', endpoints.register, ({ data }) => ({
+ data: { user: { ...currentProfile, ...data }, token: fakeToken },
+}))
+
+register('POST', endpoints.resendVerificationCodeForRegister, () => ({
+ data: { message: 'کد جدید ارسال شد' },
+}))
+
+register('POST', endpoints.forgotPassword, () => ({
+ data: { message: 'کد بازیابی ارسال شد' },
+}))
+
+register('POST', endpoints.verifyForgotPasswordCode, () => ({
+ data: { token: fakeToken },
+}))
+
+register('POST', endpoints.resetPassword, () => ({
+ data: { message: 'رمز عبور با موفقیت تغییر کرد' },
+}))
+
+register('POST', endpoints.logout, () => ({ data: { message: 'خروج موفق' } }))
+
+register('GET', endpoints.getProfile, () => ({ data: currentProfile }))
+
+register('PUT', endpoints.updateProfile, ({ data }) => {
+ Object.assign(currentProfile, {
+ firstName: data.firstName ?? currentProfile.firstName,
+ lastName: data.lastName ?? currentProfile.lastName,
+ phoneNumber: data.phoneNumber ?? currentProfile.phoneNumber,
+ nationalCode: data.nationalCode ?? currentProfile.nationalCode,
+ })
+ if (data.provinceId) {
+ currentProfile.address = currentProfile.address || {}
+ currentProfile.address.province = { id: data.provinceId, name: '' }
+ }
+ if (data.cityId) {
+ currentProfile.address = currentProfile.address || {}
+ currentProfile.address.city = { id: data.cityId, name: '' }
+ }
+ if (data.address) {
+ currentProfile.address = { ...currentProfile.address, address: data.address }
+ }
+ currentProfile.profile = {
+ ...currentProfile.profile,
+ bio: data.bio ?? currentProfile.profile?.bio,
+ birthDate: data.birthDate ?? currentProfile.profile?.birthDate,
+ maritalStatus: data.maritalStatus ?? currentProfile.profile?.maritalStatus,
+ gender: data.gender ?? currentProfile.profile?.gender,
+ }
+ return { data: currentProfile }
+})
+
+register('POST', endpoints.completeProfile, ({ data }) => ({
+ data: { user: { ...currentProfile, ...data } },
+}))
+
+register('GET', endpoints.getRegistrationQuestionVideo, () => ({
+ data: { url: '', id: 0 },
+}))
+
+register('POST', endpoints.uploadMediaTemporary, () => {
+ const id = makeId()
+ return {
+ data: {
+ id,
+ uploadId: id,
+ url: `https://picsum.photos/seed/${id}/240/240`,
+ },
+ }
+})
diff --git a/src/services/mock/routes/common.js b/src/services/mock/routes/common.js
new file mode 100644
index 0000000..3b556e2
--- /dev/null
+++ b/src/services/mock/routes/common.js
@@ -0,0 +1,9 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { cities, provinces } from '@/services/mock/fixtures/common'
+
+register('GET', endpoints.provinceList, () => ({ data: provinces }))
+
+register('GET', endpoints.citiesList, ({ params }) => ({
+ data: cities[params.provinceId] || [],
+}))
diff --git a/src/services/mock/routes/student-courses.js b/src/services/mock/routes/student-courses.js
new file mode 100644
index 0000000..eda8f51
--- /dev/null
+++ b/src/services/mock/routes/student-courses.js
@@ -0,0 +1,24 @@
+import { register } from '@/services/mock/registry'
+import { endpoints } from '@/services/api/endpoints'
+import { studentCourses } from '@/services/mock/fixtures/student-courses'
+import { findOrThrow, paginate } from '@/services/mock/helpers'
+
+const filterByStatus = (status) => {
+ if (!status) return studentCourses
+ if (status === 'current') {
+ return studentCourses.filter((c) => ['watching', 'waitForExam'].includes(c.status))
+ }
+ if (status === 'ended') {
+ return studentCourses.filter((c) => ['completed', 'failed'].includes(c.status))
+ }
+ return studentCourses.filter((c) => c.status === status)
+}
+
+register('GET', endpoints.getStudentCourses, ({ query }) => {
+ const list = filterByStatus(query.status)
+ return paginate(list, query)
+})
+
+register('GET', endpoints.showStudentCourse, ({ params }) => ({
+ data: findOrThrow(studentCourses, params.id),
+}))
diff --git a/src/services/query/admin-assignments.js b/src/services/query/admin-assignments.js
new file mode 100644
index 0000000..ef22fd0
--- /dev/null
+++ b/src/services/query/admin-assignments.js
@@ -0,0 +1,95 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminAssignment,
+ apiDeleteAdminAssignment,
+ apiGetAdminAssignmentSubmissions,
+ apiGetAdminAssignments,
+ apiReviewAdminAssignmentSubmission,
+ apiShowAdminAssignment,
+ apiShowAdminAssignmentSubmission,
+ apiUpdateAdminAssignment,
+} from '@/services/api/admin-assignments'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminAssignmentsKeys = {
+ all: ['admin', 'assignments'],
+ list: (filters, pagination) => ['admin', 'assignments', 'list', filters, pagination],
+ detail: (id) => ['admin', 'assignments', 'detail', id],
+ submissions: (assignmentId, filters, pagination) => [
+ 'admin',
+ 'assignments',
+ 'submissions',
+ assignmentId,
+ filters,
+ pagination,
+ ],
+ submissionDetail: (assignmentId, submissionId) => [
+ 'admin',
+ 'assignments',
+ 'submissions',
+ assignmentId,
+ 'detail',
+ submissionId,
+ ],
+}
+
+export const useAdminAssignmentsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'assignments', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminAssignments({
+ ...cleanFilters(filtersRef.value),
+ ...paginationRef.value,
+ }),
+ ...options,
+ })
+
+export const useAdminAssignmentQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'assignments', 'detail', idRef],
+ queryFn: () => apiShowAdminAssignment(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAdminAssignmentSubmissionsQuery = (
+ assignmentIdRef,
+ filtersRef,
+ paginationRef,
+ options = {}
+) =>
+ useQuery({
+ queryKey: ['admin', 'assignments', 'submissions', assignmentIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminAssignmentSubmissions(assignmentIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAdminAssignmentSubmissionQuery = (assignmentIdRef, submissionIdRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'assignments', 'submissions', assignmentIdRef, 'detail', submissionIdRef],
+ queryFn: () => apiShowAdminAssignmentSubmission(assignmentIdRef.value, submissionIdRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminAssignmentMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminAssignment(payload) })
+
+export const useUpdateAdminAssignmentMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiUpdateAdminAssignment(id, payload),
+ })
+
+export const useDeleteAdminAssignmentMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminAssignment(id) })
+
+export const useReviewAdminAssignmentSubmissionMutation = () =>
+ useMutation({
+ mutationFn: ({ assignmentId, submissionId, payload }) =>
+ apiReviewAdminAssignmentSubmission(assignmentId, submissionId, payload),
+ })
diff --git a/src/services/query/admin-consultations.js b/src/services/query/admin-consultations.js
new file mode 100644
index 0000000..aba82f3
--- /dev/null
+++ b/src/services/query/admin-consultations.js
@@ -0,0 +1,41 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiChangeAdminConsultationStatus,
+ apiGetAdminConsultations,
+ apiSendAdminConsultationMessage,
+ apiShowAdminConsultation,
+} from '@/services/api/admin-consultations'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminConsultationsKeys = {
+ all: ['admin', 'consultations'],
+ list: (filters, pagination) => ['admin', 'consultations', 'list', filters, pagination],
+ detail: (id) => ['admin', 'consultations', 'detail', id],
+}
+
+export const useAdminConsultationsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'consultations', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminConsultations({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminConsultationQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'consultations', 'detail', idRef],
+ queryFn: () => apiShowAdminConsultation(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useSendAdminConsultationMessageMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiSendAdminConsultationMessage(id, payload),
+ })
+
+export const useChangeAdminConsultationStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangeAdminConsultationStatus(id, payload),
+ })
diff --git a/src/services/query/admin-course-templates.js b/src/services/query/admin-course-templates.js
new file mode 100644
index 0000000..ad55684
--- /dev/null
+++ b/src/services/query/admin-course-templates.js
@@ -0,0 +1,126 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminCourseTemplate,
+ apiAddAdminTemplateStudent,
+ apiAttachAdminTemplateSession,
+ apiChangeAdminCourseTemplateStatus,
+ apiDeleteAdminCourseTemplate,
+ apiDetachAdminTemplateSession,
+ apiGetAdminCourseTemplates,
+ apiGetAdminTemplateSessions,
+ apiGetAdminTemplateStudents,
+ apiRemoveAdminTemplateStudent,
+ apiShowAdminCourseTemplate,
+ apiUpdateAdminCourseTemplate,
+} from '@/services/api/admin-course-templates'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminCourseTemplatesKeys = {
+ all: ['admin', 'course-templates'],
+ list: (filters, pagination) => ['admin', 'course-templates', 'list', filters, pagination],
+ detail: (id) => ['admin', 'course-templates', 'detail', id],
+ students: (templateId, filters, pagination) => [
+ 'admin',
+ 'course-templates',
+ 'students',
+ templateId,
+ filters,
+ pagination,
+ ],
+ sessions: (templateId, filters, pagination) => [
+ 'admin',
+ 'course-templates',
+ 'sessions',
+ templateId,
+ filters,
+ pagination,
+ ],
+}
+
+export const useAdminCourseTemplatesListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'course-templates', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminCourseTemplates({
+ ...cleanFilters(filtersRef.value),
+ ...paginationRef.value,
+ }),
+ ...options,
+ })
+
+export const useAdminCourseTemplateQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'course-templates', 'detail', idRef],
+ queryFn: () => apiShowAdminCourseTemplate(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminCourseTemplateMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminCourseTemplate(payload) })
+
+export const useUpdateAdminCourseTemplateMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiUpdateAdminCourseTemplate(id, payload),
+ })
+
+export const useDeleteAdminCourseTemplateMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminCourseTemplate(id) })
+
+export const useChangeAdminCourseTemplateStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangeAdminCourseTemplateStatus(id, payload),
+ })
+
+export const useAdminTemplateStudentsQuery = (
+ templateIdRef,
+ filtersRef,
+ paginationRef,
+ options = {}
+) =>
+ useQuery({
+ queryKey: ['admin', 'course-templates', 'students', templateIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminTemplateStudents(templateIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAddAdminTemplateStudentMutation = () =>
+ useMutation({
+ mutationFn: ({ templateId, payload }) => apiAddAdminTemplateStudent(templateId, payload),
+ })
+
+export const useRemoveAdminTemplateStudentMutation = () =>
+ useMutation({
+ mutationFn: ({ templateId, userId }) => apiRemoveAdminTemplateStudent(templateId, userId),
+ })
+
+export const useAdminTemplateSessionsQuery = (
+ templateIdRef,
+ filtersRef,
+ paginationRef,
+ options = {}
+) =>
+ useQuery({
+ queryKey: ['admin', 'course-templates', 'sessions', templateIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminTemplateSessions(templateIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAttachAdminTemplateSessionMutation = () =>
+ useMutation({
+ mutationFn: ({ templateId, payload }) => apiAttachAdminTemplateSession(templateId, payload),
+ })
+
+export const useDetachAdminTemplateSessionMutation = () =>
+ useMutation({
+ mutationFn: ({ templateId, sessionId }) => apiDetachAdminTemplateSession(templateId, sessionId),
+ })
diff --git a/src/services/query/admin-courses.js b/src/services/query/admin-courses.js
new file mode 100644
index 0000000..87f3f9b
--- /dev/null
+++ b/src/services/query/admin-courses.js
@@ -0,0 +1,49 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminCourse,
+ apiChangeAdminCourseStatus,
+ apiDeleteAdminCourse,
+ apiGetAdminCourses,
+ apiShowAdminCourse,
+ apiUpdateAdminCourse,
+} from '@/services/api/admin-courses'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminCoursesKeys = {
+ all: ['admin', 'courses'],
+ list: (filters, pagination) => ['admin', 'courses', 'list', filters, pagination],
+ detail: (id) => ['admin', 'courses', 'detail', id],
+}
+
+export const useAdminCoursesListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'courses', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminCourses({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminCourseQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'courses', 'detail', idRef],
+ queryFn: () => apiShowAdminCourse(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminCourseMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminCourse(payload) })
+
+export const useUpdateAdminCourseMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiUpdateAdminCourse(id, payload),
+ })
+
+export const useDeleteAdminCourseMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminCourse(id) })
+
+export const useChangeAdminCourseStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangeAdminCourseStatus(id, payload),
+ })
diff --git a/src/services/query/admin-exams.js b/src/services/query/admin-exams.js
new file mode 100644
index 0000000..a665e2c
--- /dev/null
+++ b/src/services/query/admin-exams.js
@@ -0,0 +1,77 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminExam,
+ apiDeleteAdminExam,
+ apiGetAdminExams,
+ apiGetAdminExamParticipants,
+ apiShowAdminExam,
+ apiShowAdminExamParticipant,
+ apiUpdateAdminExam,
+} from '@/services/api/admin-exams'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminExamsKeys = {
+ all: ['admin', 'exams'],
+ list: (filters, pagination) => ['admin', 'exams', 'list', filters, pagination],
+ detail: (id) => ['admin', 'exams', 'detail', id],
+ participants: (examId, filters, pagination) => [
+ 'admin',
+ 'exams',
+ 'participants',
+ examId,
+ filters,
+ pagination,
+ ],
+ participantDetail: (examId, participantId) => [
+ 'admin',
+ 'exams',
+ 'participants',
+ examId,
+ 'detail',
+ participantId,
+ ],
+}
+
+export const useAdminExamsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'exams', 'list', filtersRef, paginationRef],
+ queryFn: () => apiGetAdminExams({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminExamQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'exams', 'detail', idRef],
+ queryFn: () => apiShowAdminExam(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAdminExamParticipantsQuery = (examIdRef, filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'exams', 'participants', examIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminExamParticipants(examIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAdminExamParticipantQuery = (examIdRef, participantIdRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'exams', 'participants', examIdRef, 'detail', participantIdRef],
+ queryFn: () => apiShowAdminExamParticipant(examIdRef.value, participantIdRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminExamMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminExam(payload) })
+
+export const useUpdateAdminExamMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiUpdateAdminExam(id, payload) })
+
+export const useDeleteAdminExamMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminExam(id) })
diff --git a/src/services/query/admin-pending-students.js b/src/services/query/admin-pending-students.js
new file mode 100644
index 0000000..74bec7c
--- /dev/null
+++ b/src/services/query/admin-pending-students.js
@@ -0,0 +1,39 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiChangePendingStudentStatus,
+ apiDownloadPendingStudentPdf,
+ apiGetPendingStudents,
+ apiShowPendingStudent,
+} from '@/services/api/admin-pending-students'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminPendingStudentsKeys = {
+ all: ['admin', 'pending-students'],
+ list: (filters, pagination) => ['admin', 'pending-students', 'list', filters, pagination],
+ detail: (id) => ['admin', 'pending-students', 'detail', id],
+}
+
+export const usePendingStudentsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'pending-students', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetPendingStudents({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const usePendingStudentQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'pending-students', 'detail', idRef],
+ queryFn: () => apiShowPendingStudent(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useChangePendingStudentStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangePendingStudentStatus(id, payload),
+ })
+
+export const useDownloadPendingStudentPdfMutation = () =>
+ useMutation({ mutationFn: (id) => apiDownloadPendingStudentPdf(id) })
diff --git a/src/services/query/admin-sessions.js b/src/services/query/admin-sessions.js
new file mode 100644
index 0000000..03405a6
--- /dev/null
+++ b/src/services/query/admin-sessions.js
@@ -0,0 +1,74 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminSession,
+ apiChangeAdminSessionStatus,
+ apiDeleteAdminSession,
+ apiGetAdminSessions,
+ apiGetSessionAttendance,
+ apiShowAdminSession,
+ apiUpdateAdminSession,
+} from '@/services/api/admin-sessions'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminSessionsKeys = {
+ all: ['admin', 'sessions'],
+ list: (filters, pagination) => ['admin', 'sessions', 'list', filters, pagination],
+ detail: (id) => ['admin', 'sessions', 'detail', id],
+ attendance: (sessionId, filters, pagination) => [
+ 'admin',
+ 'sessions',
+ 'attendance',
+ sessionId,
+ filters,
+ pagination,
+ ],
+}
+
+export const useAdminSessionsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'sessions', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminSessions({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminSessionQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'sessions', 'detail', idRef],
+ queryFn: () => apiShowAdminSession(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAdminSessionAttendanceQuery = (
+ sessionIdRef,
+ filtersRef,
+ paginationRef,
+ options = {}
+) =>
+ useQuery({
+ queryKey: ['admin', 'sessions', 'attendance', sessionIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetSessionAttendance(sessionIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAddAdminSessionMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminSession(payload) })
+
+export const useUpdateAdminSessionMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiUpdateAdminSession(id, payload),
+ })
+
+export const useDeleteAdminSessionMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminSession(id) })
+
+export const useChangeAdminSessionStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangeAdminSessionStatus(id, payload),
+ })
diff --git a/src/services/query/admin-terms.js b/src/services/query/admin-terms.js
new file mode 100644
index 0000000..0c1f6c7
--- /dev/null
+++ b/src/services/query/admin-terms.js
@@ -0,0 +1,119 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminTerm,
+ apiAddAdminTermCourses,
+ apiAddAdminTermStudents,
+ apiChangeAdminTermStatus,
+ apiCloneAdminTerm,
+ apiDeleteAdminTerm,
+ apiGetAdminTerms,
+ apiGetAdminTermCourses,
+ apiGetAdminTermStudents,
+ apiRemoveAdminTermCourse,
+ apiRemoveAdminTermStudent,
+ apiShowAdminTerm,
+ apiToggleAdminTermStudentLeave,
+ apiUpdateAdminTerm,
+} from '@/services/api/admin-terms'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminTermsKeys = {
+ all: ['admin', 'terms'],
+ list: (filters, pagination) => ['admin', 'terms', 'list', filters, pagination],
+ detail: (id) => ['admin', 'terms', 'detail', id],
+ students: (termId, filters, pagination) => [
+ 'admin',
+ 'terms',
+ 'students',
+ termId,
+ filters,
+ pagination,
+ ],
+ courses: (termId, filters, pagination) => [
+ 'admin',
+ 'terms',
+ 'courses',
+ termId,
+ filters,
+ pagination,
+ ],
+}
+
+export const useAdminTermsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'terms', 'list', filtersRef, paginationRef],
+ queryFn: () => apiGetAdminTerms({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminTermQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'terms', 'detail', idRef],
+ queryFn: () => apiShowAdminTerm(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminTermMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminTerm(payload) })
+
+export const useUpdateAdminTermMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiUpdateAdminTerm(id, payload) })
+
+export const useDeleteAdminTermMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminTerm(id) })
+
+export const useCloneAdminTermMutation = () =>
+ useMutation({ mutationFn: (id) => apiCloneAdminTerm(id) })
+
+export const useChangeAdminTermStatusMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiChangeAdminTermStatus(id, payload) })
+
+export const useAdminTermStudentsQuery = (termIdRef, filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'terms', 'students', termIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminTermStudents(termIdRef.value, {
+ ...cleanFilters(filtersRef.value),
+ ...paginationRef.value,
+ }),
+ ...options,
+ })
+
+export const useAddAdminTermStudentsMutation = () =>
+ useMutation({
+ mutationFn: ({ termId, payload }) => apiAddAdminTermStudents(termId, payload),
+ })
+
+export const useRemoveAdminTermStudentMutation = () =>
+ useMutation({
+ mutationFn: ({ termId, userId }) => apiRemoveAdminTermStudent(termId, userId),
+ })
+
+export const useToggleAdminTermStudentLeaveMutation = () =>
+ useMutation({
+ mutationFn: ({ termId, userId, payload }) =>
+ apiToggleAdminTermStudentLeave(termId, userId, payload),
+ })
+
+export const useAdminTermCoursesQuery = (termIdRef, filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'terms', 'courses', termIdRef, filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminTermCourses(termIdRef.value, {
+ ...cleanFilters(filtersRef?.value || {}),
+ ...paginationRef?.value,
+ }),
+ ...options,
+ })
+
+export const useAddAdminTermCoursesMutation = () =>
+ useMutation({
+ mutationFn: ({ termId, payload }) => apiAddAdminTermCourses(termId, payload),
+ })
+
+export const useRemoveAdminTermCourseMutation = () =>
+ useMutation({
+ mutationFn: ({ termId, courseId }) => apiRemoveAdminTermCourse(termId, courseId),
+ })
diff --git a/src/services/query/admin-tickets.js b/src/services/query/admin-tickets.js
new file mode 100644
index 0000000..03488d9
--- /dev/null
+++ b/src/services/query/admin-tickets.js
@@ -0,0 +1,41 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiChangeAdminTicketStatus,
+ apiGetAdminTickets,
+ apiSendAdminTicketMessage,
+ apiShowAdminTicket,
+} from '@/services/api/admin-tickets'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminTicketsKeys = {
+ all: ['admin', 'tickets'],
+ list: (filters, pagination) => ['admin', 'tickets', 'list', filters, pagination],
+ detail: (id) => ['admin', 'tickets', 'detail', id],
+}
+
+export const useAdminTicketsListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'tickets', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetAdminTickets({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminTicketQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'tickets', 'detail', idRef],
+ queryFn: () => apiShowAdminTicket(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useSendAdminTicketMessageMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiSendAdminTicketMessage(id, payload),
+ })
+
+export const useChangeAdminTicketStatusMutation = () =>
+ useMutation({
+ mutationFn: ({ id, payload }) => apiChangeAdminTicketStatus(id, payload),
+ })
diff --git a/src/services/query/admin-users.js b/src/services/query/admin-users.js
new file mode 100644
index 0000000..515e45b
--- /dev/null
+++ b/src/services/query/admin-users.js
@@ -0,0 +1,58 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiAddAdminUser,
+ apiChangeAdminUserStatus,
+ apiDeleteAdminUser,
+ apiGetAdminRoles,
+ apiGetAdminUsers,
+ apiShowAdminUser,
+ apiUpdateAdminUser,
+ apiUpdateAdminUserRole,
+} from '@/services/api/admin-users'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const adminUsersKeys = {
+ all: ['admin', 'users'],
+ list: (filters, pagination) => ['admin', 'users', 'list', filters, pagination],
+ detail: (id) => ['admin', 'users', 'detail', id],
+ roles: () => ['admin', 'users', 'roles'],
+}
+
+export const useAdminUsersListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'users', 'list', filtersRef, paginationRef],
+ queryFn: () => apiGetAdminUsers({ ...cleanFilters(filtersRef.value), ...paginationRef.value }),
+ ...options,
+ })
+
+export const useAdminUserQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['admin', 'users', 'detail', idRef],
+ queryFn: () => apiShowAdminUser(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAdminRolesListQuery = (options = {}) =>
+ useQuery({
+ queryKey: adminUsersKeys.roles(),
+ queryFn: () => apiGetAdminRoles(),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useAddAdminUserMutation = () =>
+ useMutation({ mutationFn: (payload) => apiAddAdminUser(payload) })
+
+export const useUpdateAdminUserMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiUpdateAdminUser(id, payload) })
+
+export const useUpdateAdminUserRoleMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiUpdateAdminUserRole(id, payload) })
+
+export const useChangeAdminUserStatusMutation = () =>
+ useMutation({ mutationFn: ({ id, payload }) => apiChangeAdminUserStatus(id, payload) })
+
+export const useDeleteAdminUserMutation = () =>
+ useMutation({ mutationFn: (id) => apiDeleteAdminUser(id) })
diff --git a/src/services/query/auth.js b/src/services/query/auth.js
new file mode 100644
index 0000000..b794f72
--- /dev/null
+++ b/src/services/query/auth.js
@@ -0,0 +1,65 @@
+import { useMutation, useQuery } from '@tanstack/vue-query'
+
+import {
+ apiCompleteProfile,
+ apiForgotPassword,
+ apiGetProfile,
+ apiGetRegistrationQuestionVideo,
+ apiLogin,
+ apiLoginWithCode,
+ apiLogout,
+ apiRegister,
+ apiResendVerificationCode,
+ apiResetPassword,
+ apiUpdateProfile,
+ apiUploadTemporary,
+ apiVerifyCode,
+ apiVerifyForgotPasswordCode,
+} from '@/services/api/auth'
+
+export const authKeys = {
+ profile: () => ['auth', 'profile'],
+ registrationVideo: () => ['auth', 'registration-video'],
+}
+
+export const useLoginMutation = () => useMutation({ mutationFn: apiLogin })
+
+export const useLoginWithCodeMutation = () => useMutation({ mutationFn: apiLoginWithCode })
+
+export const useRegisterMutation = () => useMutation({ mutationFn: apiRegister })
+
+export const useVerifyCodeMutation = () => useMutation({ mutationFn: apiVerifyCode })
+
+export const useResendVerificationCodeMutation = () =>
+ useMutation({ mutationFn: apiResendVerificationCode })
+
+export const useForgotPasswordMutation = () => useMutation({ mutationFn: apiForgotPassword })
+
+export const useVerifyForgotPasswordCodeMutation = () =>
+ useMutation({ mutationFn: apiVerifyForgotPasswordCode })
+
+export const useResetPasswordMutation = () => useMutation({ mutationFn: apiResetPassword })
+
+export const useLogoutMutation = () => useMutation({ mutationFn: apiLogout })
+
+export const useGetProfileQuery = (options = {}) =>
+ useQuery({
+ queryKey: authKeys.profile(),
+ queryFn: () => apiGetProfile(),
+ select: (response) => response?.data?.user ?? response?.data ?? response,
+ ...options,
+ })
+
+export const useCompleteProfileMutation = () => useMutation({ mutationFn: apiCompleteProfile })
+
+export const useUpdateProfileMutation = () => useMutation({ mutationFn: apiUpdateProfile })
+
+export const useGetRegistrationVideoQuery = (options = {}) =>
+ useQuery({
+ queryKey: authKeys.registrationVideo(),
+ queryFn: () => apiGetRegistrationQuestionVideo(),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useUploadTemporaryMutation = () => useMutation({ mutationFn: apiUploadTemporary })
diff --git a/src/services/query/common.js b/src/services/query/common.js
new file mode 100644
index 0000000..2cc0d78
--- /dev/null
+++ b/src/services/query/common.js
@@ -0,0 +1,24 @@
+import { useQuery } from '@tanstack/vue-query'
+
+import { apiGetCitiesOfProvince, apiGetProvinces } from '@/services/api/common'
+
+export const commonKeys = {
+ provinces: () => ['common', 'provinces'],
+ cities: (provinceId) => ['common', 'cities', provinceId],
+}
+
+export const useGetProvincesQuery = (options = {}) =>
+ useQuery({
+ queryKey: commonKeys.provinces(),
+ queryFn: () => apiGetProvinces(),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
+
+export const useGetCitiesOfProvinceQuery = (provinceIdRef, options = {}) =>
+ useQuery({
+ queryKey: ['common', 'cities', provinceIdRef],
+ queryFn: () => apiGetCitiesOfProvince(provinceIdRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
diff --git a/src/services/query/index.js b/src/services/query/index.js
new file mode 100644
index 0000000..46ff5b7
--- /dev/null
+++ b/src/services/query/index.js
@@ -0,0 +1,3 @@
+export * from '@/services/query/common'
+export * from '@/services/query/auth'
+export * from '@/services/query/admin-users'
diff --git a/src/services/query/student-courses.js b/src/services/query/student-courses.js
new file mode 100644
index 0000000..3e683d8
--- /dev/null
+++ b/src/services/query/student-courses.js
@@ -0,0 +1,29 @@
+import { useQuery } from '@tanstack/vue-query'
+
+import { apiGetStudentCourses, apiShowStudentCourse } from '@/services/api/student-courses'
+import { cleanFilters } from '@/utils/clean-filters'
+
+export const studentCoursesKeys = {
+ all: ['student', 'courses'],
+ list: (filters, pagination) => ['student', 'courses', 'list', filters, pagination],
+ detail: (id) => ['student', 'courses', 'detail', id],
+}
+
+export const useStudentCoursesListQuery = (filtersRef, paginationRef, options = {}) =>
+ useQuery({
+ queryKey: ['student', 'courses', 'list', filtersRef, paginationRef],
+ queryFn: () =>
+ apiGetStudentCourses({
+ ...cleanFilters(filtersRef.value),
+ ...paginationRef.value,
+ }),
+ ...options,
+ })
+
+export const useStudentCourseQuery = (idRef, options = {}) =>
+ useQuery({
+ queryKey: ['student', 'courses', 'detail', idRef],
+ queryFn: () => apiShowStudentCourse(idRef.value),
+ select: (response) => response?.data ?? response,
+ ...options,
+ })
diff --git a/src/store/auth.js b/src/store/auth.js
new file mode 100644
index 0000000..7dadc28
--- /dev/null
+++ b/src/store/auth.js
@@ -0,0 +1,29 @@
+import { computed, ref } from 'vue'
+import { defineStore } from 'pinia'
+
+import { tokenService } from '@/services/api/token-service'
+
+export const useAuthStore = defineStore('auth', () => {
+ const user = ref(tokenService.getUserInfo())
+
+ const isAuthenticated = computed(() => !!tokenService.getToken() && !!user.value)
+ const role = computed(() => user.value?.role || user.value?.roleName || null)
+
+ const setUser = (userData) => {
+ user.value = userData
+ tokenService.saveUserInfo(userData)
+ }
+
+ const clearUser = () => {
+ user.value = null
+ tokenService.clearAll()
+ }
+
+ return {
+ user,
+ role,
+ isAuthenticated,
+ setUser,
+ clearUser,
+ }
+})
diff --git a/src/store/modal.js b/src/store/modal.js
new file mode 100644
index 0000000..6fb3bec
--- /dev/null
+++ b/src/store/modal.js
@@ -0,0 +1,33 @@
+import { defineStore } from 'pinia'
+import { ref, computed } from 'vue'
+
+export const useModalStore = defineStore('modal', () => {
+ const modals = ref([])
+
+ const isModal = (name) => modals.value.some((x) => x.name === name)
+ const getModal = (name) => modals.value.find((x) => x.name === name)
+ const getActiveModal = computed(() => modals.value.at(-1))
+
+ const openModal = (name, data) => {
+ if (!modals.value.some((x) => x.name === name)) {
+ modals.value.push({ name, data })
+ }
+ }
+
+ const closeModal = (name) => {
+ if (name) {
+ modals.value = modals.value.filter((x) => x.name !== name)
+ } else if (modals.value.length > 0) {
+ modals.value.pop()
+ }
+ }
+
+ return {
+ modals,
+ getActiveModal,
+ isModal,
+ getModal,
+ openModal,
+ closeModal,
+ }
+})
diff --git a/src/store/ui.js b/src/store/ui.js
new file mode 100644
index 0000000..3fb5417
--- /dev/null
+++ b/src/store/ui.js
@@ -0,0 +1,27 @@
+import { ref } from 'vue'
+import { defineStore } from 'pinia'
+
+export const useUIStore = defineStore('ui', () => {
+ const isSidebarOpen = ref(false)
+ const pageTitle = ref('')
+
+ const toggleSidebar = () => {
+ isSidebarOpen.value = !isSidebarOpen.value
+ }
+
+ const setSidebarState = (open) => {
+ isSidebarOpen.value = open
+ }
+
+ const setPageTitle = (title) => {
+ pageTitle.value = title
+ }
+
+ return {
+ isSidebarOpen,
+ pageTitle,
+ toggleSidebar,
+ setSidebarState,
+ setPageTitle,
+ }
+})
diff --git a/src/utils/api-error.js b/src/utils/api-error.js
new file mode 100644
index 0000000..e6cc67d
--- /dev/null
+++ b/src/utils/api-error.js
@@ -0,0 +1,40 @@
+export class ApiError extends Error {
+ constructor(message) {
+ super(message)
+ this.name = 'ApiError'
+ }
+}
+
+export function normalizeApiError(error_) {
+ if (!error_?.response && !error_?.request) {
+ return error_
+ }
+
+ const error = error_.response
+ ? new ApiError(`Response error: ${error_?.response?.statusText}`)
+ : new ApiError(`Network error: ${error_?.message}`)
+
+ error.statusCode =
+ !error_.response && error_.code === 'ECONNABORTED'
+ ? 408
+ : !error_.response && !error.isTimeoutError
+ ? 599
+ : error_?.response?.status || 500
+
+ error.errorType = 'api'
+ error.url = (error_?.config?.baseURL || '') + (error_?.config?.url || '')
+ error.headers = error_?.config?.headers
+ error.data = error_?.config?.data
+ error.timeout = error_?.config?.timeout
+
+ if (error.url) {
+ try {
+ const parsedUrl = new URL(error.url)
+ error.hostname = parsedUrl.hostname
+ error.pathname = parsedUrl.pathname
+ error.search = parsedUrl.search
+ } catch {}
+ }
+
+ return error
+}
diff --git a/src/utils/clean-filters.js b/src/utils/clean-filters.js
new file mode 100644
index 0000000..5a14b6d
--- /dev/null
+++ b/src/utils/clean-filters.js
@@ -0,0 +1,8 @@
+export const cleanFilters = (filters) =>
+ Object.fromEntries(
+ Object.entries(filters).filter(
+ ([, value]) => value !== '' && value !== null && value !== undefined
+ )
+ )
+
+export default cleanFilters
diff --git a/src/utils/convert-check-digits.js b/src/utils/convert-check-digits.js
new file mode 100644
index 0000000..b31c955
--- /dev/null
+++ b/src/utils/convert-check-digits.js
@@ -0,0 +1,11 @@
+const persianNumbers = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g]
+const arabicNumbers = [/٠/g, /١/g, /٢/g, /٣/g, /٤/g, /٥/g, /٦/g, /٧/g, /٨/g, /٩/g]
+
+export const convertToEnNumber = (str) => {
+ if (typeof str !== 'string') return ''
+ let result = str
+ for (let i = 0; i < 10; i += 1) {
+ result = result.replace(persianNumbers[i], i).replace(arabicNumbers[i], i)
+ }
+ return result
+}
diff --git a/src/utils/convert-to-camel-snake.js b/src/utils/convert-to-camel-snake.js
new file mode 100644
index 0000000..4c490b8
--- /dev/null
+++ b/src/utils/convert-to-camel-snake.js
@@ -0,0 +1,19 @@
+import isArray from 'lodash/isArray'
+import isObject from 'lodash/isObject'
+import camelCase from 'lodash/camelCase'
+import snakeCase from 'lodash/snakeCase'
+import transform from 'lodash/transform'
+
+export function camelize(obj) {
+ return transform(obj, (acc, value, key, target) => {
+ const camelKey = isArray(target) ? key : camelCase(key)
+ acc[camelKey] = isObject(value) ? camelize(value) : value
+ })
+}
+
+export function snakize(obj) {
+ return transform(obj, (acc, value, key, target) => {
+ const snakeKey = isArray(target) ? key : snakeCase(key)
+ acc[snakeKey] = isObject(value) ? snakize(value) : value
+ })
+}
diff --git a/src/utils/date-utils.js b/src/utils/date-utils.js
new file mode 100644
index 0000000..d334008
--- /dev/null
+++ b/src/utils/date-utils.js
@@ -0,0 +1,395 @@
+// Utility helper functions.
+
+function div(a, b) {
+ return Math.trunc(a / b)
+}
+
+function mod(a, b) {
+ return a - Math.trunc(a / b) * b
+}
+
+/*
+ Jalaali years starting the 33-year rule.
+*/
+const breaks = [
+ -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097, 2192, 2262, 2324, 2394,
+ 2456, 3178,
+]
+
+/*
+ This function determines if the Jalaali (Persian) year is
+ leap (366-day long) or is the common year (365 days)
+
+ @param jy Jalaali calendar year (-61 to 3177)
+ @returns number of years since the last leap year (0 to 4)
+ */
+function jalCalLeap(jy) {
+ const bl = breaks.length
+ let jp = breaks[0]
+ let jm
+ let jump
+ let leap
+ let n
+ let i
+
+ if (jy < jp || jy >= breaks[bl - 1]) {
+ throw new Error(`Invalid Jalaali year ${jy}`)
+ }
+
+ for (i = 1; i < bl; i += 1) {
+ jm = breaks[i]
+ jump = jm - jp
+ if (jy < jm) {
+ break
+ }
+ jp = jm
+ }
+ n = jy - jp
+
+ if (jump - n < 6) {
+ n = n - jump + div(jump + 4, 33) * 33
+ }
+ leap = mod(mod(n + 1, 33) - 1, 4)
+ if (leap === -1) {
+ leap = 4
+ }
+
+ return leap
+}
+
+/*
+ Is this a leap year or not?
+*/
+function isLeapJalaaliYear(jy) {
+ return jalCalLeap(jy) === 0
+}
+
+/*
+ Number of days in a given month in a Jalaali year.
+*/
+export function jalaaliMonthLength(jy, jm) {
+ if (jm <= 6) return 31
+ if (jm <= 11) return 30
+ if (isLeapJalaaliYear(jy)) return 30
+ return 29
+}
+
+/*
+ This function determines if the Jalaali (Persian) year is
+ leap (366-day long) or is the common year (365 days), and
+ finds the day in March (Gregorian calendar) of the first
+ day of the Jalaali year (jy).
+
+ @param jy Jalaali calendar year (-61 to 3177)
+ @param withoutLeap when don't need leap (true or false) default is false
+ @return
+ leap: number of years since the last leap year (0 to 4)
+ gy: Gregorian year of the beginning of Jalaali year
+ march: the March day of Farvardin the 1st (1st day of jy)
+ @see: http://www.astro.uni.torun.pl/~kb/Papers/EMP/PersianC-EMP.htm
+ @see: http://www.fourmilab.ch/documents/calendar/
+*/
+function jalCal(jy, withoutLeap) {
+ const bl = breaks.length
+ const gy = jy + 621
+ let leapJ = -14
+ let jp = breaks[0]
+ let jm
+ let jump
+ let leap
+ let n
+ let i
+
+ if (jy < jp || jy >= breaks[bl - 1]) {
+ throw new Error(`Invalid Jalaali year ${jy}`)
+ }
+
+ // Find the limiting years for the Jalaali year jy.
+ for (i = 1; i < bl; i += 1) {
+ jm = breaks[i]
+ jump = jm - jp
+ if (jy < jm) {
+ break
+ }
+ leapJ = leapJ + div(jump, 33) * 8 + div(mod(jump, 33), 4)
+ jp = jm
+ }
+ n = jy - jp
+
+ // Find the number of leap years from AD 621 to the beginning
+ // of the current Jalaali year in the Persian calendar.
+ leapJ = leapJ + div(n, 33) * 8 + div(mod(n, 33) + 3, 4)
+ if (mod(jump, 33) === 4 && jump - n === 4) {
+ leapJ += 1
+ }
+
+ // And the same in the Gregorian calendar (until the year gy).
+ const leapG = div(gy, 4) - div((div(gy, 100) + 1) * 3, 4) - 150
+
+ // Determine the Gregorian date of Farvardin the 1st.
+ const march = 20 + leapJ - leapG
+
+ // Find how many years have passed since the last leap year.
+ if (!withoutLeap) {
+ if (jump - n < 6) {
+ n = n - jump + div(jump + 4, 33) * 33
+ }
+ leap = mod(mod(n + 1, 33) - 1, 4)
+ if (leap === -1) {
+ leap = 4
+ }
+ }
+
+ return {
+ leap,
+ gy,
+ march,
+ }
+}
+
+/*
+ Calculates the Julian Day number from Gregorian or Julian
+ calendar dates. This integer number corresponds to the noon of
+ the date (i.e. 12 hours of Universal Time).
+ The procedure was tested to be good since 1 March, -100100 (of both
+ calendars) up to a few million years into the future.
+
+ @param gy Calendar year (years BC numbered 0, -1, -2, ...)
+ @param gm Calendar month (1 to 12)
+ @param gd Calendar day of the month (1 to 28/29/30/31)
+ @return Julian Day number
+*/
+function g2d(gy, gm, gd) {
+ let d =
+ div((gy + div(gm - 8, 6) + 100_100) * 1461, 4) +
+ div(153 * mod(gm + 9, 12) + 2, 5) +
+ gd -
+ 34_840_408
+ d = d - div(div(gy + 100_100 + div(gm - 8, 6), 100) * 3, 4) + 752
+ return d
+}
+
+/*
+ Converts a date of the Jalaali calendar to the Julian Day number.
+
+ @param jy Jalaali year (1 to 3100)
+ @param jm Jalaali month (1 to 12)
+ @param jd Jalaali day (1 to 29/31)
+ @return Julian Day number
+*/
+function j2d(jy, jm, jd) {
+ const r = jalCal(jy, true)
+ return g2d(r.gy, 3, r.march) + (jm - 1) * 31 - div(jm, 7) * (jm - 7) + jd - 1
+}
+
+/*
+ Calculates Gregorian and Julian calendar dates from the Julian Day number
+ (jdn) for the period since jdn=-34839655 (i.e. the year -100100 of both
+ calendars) to some millions years ahead of the present.
+
+ @param jdn Julian Day number
+ @return
+ gy: Calendar year (years BC numbered 0, -1, -2, ...)
+ gm: Calendar month (1 to 12)
+ gd: Calendar day of the month M (1 to 28/29/30/31)
+*/
+function d2g(jdn) {
+ let j = 4 * jdn + 139_361_631
+ j = j + div(div(4 * jdn + 183_187_720, 146_097) * 3, 4) * 4 - 3908
+ const i = div(mod(j, 1461), 4) * 5 + 308
+ const gd = div(mod(i, 153), 5) + 1
+ const gm = mod(div(i, 153), 12) + 1
+ const gy = div(j, 1461) - 100_100 + div(8 - gm, 6)
+ return {
+ gy,
+ gm,
+ gd,
+ }
+}
+/*
+ Converts the Julian Day number to a date in the Jalaali calendar.
+
+ @param jdn Julian Day number
+ @return
+ jy: Jalaali year (1 to 3100)
+ jm: Jalaali month (1 to 12)
+ jd: Jalaali day (1 to 29/31)
+*/
+function d2j(jdn) {
+ const { gy } = d2g(jdn) // Calculate Gregorian year (gy).
+ let jy = gy - 621
+ let jd
+ let jm
+ let k
+ const r = jalCal(jy, false)
+ const jdn1f = g2d(gy, 3, r.march)
+
+ // Find number of days that passed since 1 Farvardin.
+ k = jdn - jdn1f
+ if (k >= 0) {
+ if (k <= 185) {
+ // The first 6 months.
+ jm = 1 + div(k, 31)
+ jd = mod(k, 31) + 1
+ return {
+ jy,
+ jm,
+ jd,
+ }
+ }
+
+ // The remaining months.
+ k -= 186
+ } else {
+ // Previous Jalaali year.
+ jy -= 1
+ k += 179
+ if (r.leap === 1) {
+ k += 1
+ }
+ }
+ jm = 7 + div(k, 30)
+ jd = mod(k, 30) + 1
+ return {
+ jy,
+ jm,
+ jd,
+ }
+}
+/*
+ Converts a Gregorian date to Jalaali.
+*/
+export function toJalaali(gy, gm, gd) {
+ let cloneGd = gd
+ let cloneGm = gm
+ let cloneGy = gy
+ if (Object.prototype.toString.call(gy) === '[object Date]') {
+ cloneGd = gy.getDate()
+ cloneGm = gy.getMonth() + 1
+ cloneGy = gy.getFullYear()
+ }
+ return d2j(g2d(cloneGy, cloneGm, cloneGd))
+}
+
+/*
+ Converts a Jalaali date to Gregorian.
+*/
+export function toGregorian(jy, jm, jd) {
+ return d2g(j2d(jy, jm, jd))
+}
+
+export function convertToJalali(gregorianDate, format = 'jYYYY/jMM/jDD') {
+ const months = 'فروردین_اردیبهشت_خرداد_تیر_مرداد_شهریور_مهر_آبان_آذر_دی_بهمن_اسفند'.split('_')
+ const weekdays = 'یک\u200Cشنبه_دوشنبه_سه\u200Cشنبه_چهارشنبه_پنج\u200Cشنبه_جمعه_شنبه'.split('_')
+
+ const date = new Date(gregorianDate)
+
+ const weekday = date.getDay()
+
+ const { jy: year, jm: month, jd: day } = toJalaali(date)
+
+ const formatMap = {
+ jYYYY: year.toString(),
+ jYY: year.toString().slice(-2),
+ jMMMM: months[month - 1],
+ jMMM: months[month - 1].slice(0, 3),
+ jMM: month.toString().padStart(2, '0'),
+ jM: month.toString(),
+ jDD: day.toString().padStart(2, '0'),
+ jD: day.toString(),
+ jdddd: weekdays[weekday],
+ jddd: weekdays[weekday].slice(0, 3),
+ }
+
+ return format.replace(
+ /jYYYY|jYY|jMMMM|jMMM|jMM|jM|jDD|jD|jdddd|jddd/g,
+ (match) => formatMap[match]
+ )
+}
+
+export function formatJalaaliDate(value, { fallback = '' } = {}) {
+ if (!value) return fallback
+ const date = new Date(value)
+ if (Number.isNaN(date.getTime())) return fallback
+ return convertToJalali(date, 'jYYYY/jMM/jDD')
+}
+
+export function formatJalaaliDateTime(value, { fallback = '', separator = ' - ' } = {}) {
+ if (!value) return fallback
+ const date = new Date(value)
+ if (Number.isNaN(date.getTime())) return fallback
+ const datePart = convertToJalali(date, 'jYYYY/jMM/jDD')
+ const hh = String(date.getHours()).padStart(2, '0')
+ const mm = String(date.getMinutes()).padStart(2, '0')
+ return `${datePart}${separator}${hh}:${mm}`
+}
+
+export function formatTime(value, { fallback = '' } = {}) {
+ if (!value) return fallback
+ const date = new Date(value)
+ if (Number.isNaN(date.getTime())) return fallback
+ const hh = String(date.getHours()).padStart(2, '0')
+ const mm = String(date.getMinutes()).padStart(2, '0')
+ return `${hh}:${mm}`
+}
+
+export function jalaaliStringToIsoDate(jalaliStr) {
+ if (!jalaliStr) return null
+ const [jy, jm, jd] = String(jalaliStr).split('/').map(Number)
+ if (!jy || !jm || !jd) return null
+ try {
+ const { gy, gm, gd } = toGregorian(jy, jm, jd)
+ const month = String(gm).padStart(2, '0')
+ const day = String(gd).padStart(2, '0')
+ return `${gy}-${month}-${day}T00:00:00.000Z`
+ } catch {
+ return null
+ }
+}
+
+export function jalaaliStringToIsoDateTime(jalaliDateTimeStr) {
+ if (!jalaliDateTimeStr) return null
+ const [datePart, timePart = '00:00'] = String(jalaliDateTimeStr).split(' ')
+ const [jy, jm, jd] = datePart.split('/').map(Number)
+ if (!jy || !jm || !jd) return null
+ try {
+ const { gy, gm, gd } = toGregorian(jy, jm, jd)
+ const month = String(gm).padStart(2, '0')
+ const day = String(gd).padStart(2, '0')
+ return `${gy}-${month}-${day}T${timePart}:00.000Z`
+ } catch {
+ return null
+ }
+}
+
+export function convertToGregorian(jalaaliDate, format = 'YYYY/MM/DD') {
+ const weekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_')
+ const months =
+ 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
+ '_'
+ )
+
+ const date = new Date(jalaaliDate)
+ const jYear = date.getFullYear()
+ const jMonth = date.getMonth()
+ const jDay = date.getDate()
+
+ const { gy: year, gm: month, gd: day } = toGregorian(jYear, jMonth + 1, jDay)
+
+ const gWeekday = new Date([year, month, day]).getDay()
+
+ const formatMap = {
+ YYYY: year.toString(),
+ YY: year.toString().slice(-2),
+ MMMM: months[month - 1],
+ MMM: months[month - 1].slice(0, 3),
+ MM: month.toString().padStart(2, '0'),
+ M: month.toString(),
+ DD: day.toString().padStart(2, '0'),
+ D: day.toString(),
+ dddd: weekdays[gWeekday],
+ ddd: weekdays[gWeekday].slice(0, 3),
+ }
+
+ return format.replace(/YYYY|YY|MMMM|MMM|MM|M|DD|D|dddd|ddd/g, (match) => formatMap[match])
+}
diff --git a/src/utils/error-handler.js b/src/utils/error-handler.js
new file mode 100644
index 0000000..2c7b3af
--- /dev/null
+++ b/src/utils/error-handler.js
@@ -0,0 +1,66 @@
+import { toast } from 'vue3-toastify'
+
+import { normalizeApiError } from './api-error'
+
+export function humanizeError(error) {
+ let currentError
+ if (error?.response || error?.request) {
+ currentError = normalizeApiError(error)
+ } else if (error instanceof Error) {
+ currentError = error
+ currentError.errorType = 'logic'
+ } else {
+ currentError = new Error('something unexpected', { cause: error })
+ currentError.errorType = 'unknown'
+ }
+
+ if (!currentError.statusCode) {
+ currentError.statusCode = 500
+ }
+ return currentError
+}
+
+export function handleApiError(error_) {
+ const data = error_?.response?.data
+ const status = error_?.response?.status
+
+ if (status === 422 && data?.errors) {
+ Object.values(data.errors).forEach((messages) => {
+ const list = Array.isArray(messages) ? messages : [messages]
+ list.forEach((msg) => toast.error(msg))
+ })
+ return
+ }
+
+ if (data?.message) {
+ toast.error(data.message)
+ return
+ }
+
+ toast.error('عملیات با خطا مواجه شد')
+}
+
+export function handleUnknownError(options) {
+ const { showToast } = { showToast: true, ...options }
+ if (showToast) {
+ toast.error('مشکلی در انجام عملیات رخ داد. لطفا دوباره امتحان کنید.')
+ }
+}
+
+export function handleError(error, options) {
+ try {
+ const { showToast } = { showToast: true, ...options }
+ const currentError = humanizeError(error)
+ if (currentError.errorType === 'logic') {
+ if (showToast) toast.error(currentError.message)
+ return
+ }
+ if (showToast && currentError.errorType === 'api') {
+ handleApiError(error)
+ return
+ }
+ if (showToast) handleUnknownError(options)
+ } catch {
+ handleUnknownError(options)
+ }
+}
diff --git a/src/utils/gallery.js b/src/utils/gallery.js
new file mode 100644
index 0000000..a36a5f2
--- /dev/null
+++ b/src/utils/gallery.js
@@ -0,0 +1,19 @@
+import loginPattern from '@/assets/images/auth/login-pattern.jpg'
+import loginPatternMobile from '@/assets/images/auth/login-pattern-mobile.png'
+import loginPatternWithLogo from '@/assets/images/auth/login-pattern-logo.jpg'
+import registrationCompleteFlower from '@/assets/images/auth/flower.png'
+import logoWhite from '@/assets/images/logo-white.png'
+import logoPinkishRed from '@/assets/images/logo-pinkish-red.png'
+import authLogo from '@/assets/images/auth/auth-logo.png'
+import VideoCover from '@/assets/images/cover.png'
+
+export const gallery = {
+ loginPattern,
+ loginPatternMobile,
+ authLogo,
+ loginPatternWithLogo,
+ logoWhite,
+ logoPinkishRed,
+ VideoCover,
+ registrationCompleteFlower,
+}
diff --git a/src/utils/global-components.js b/src/utils/global-components.js
new file mode 100644
index 0000000..8a52c05
--- /dev/null
+++ b/src/utils/global-components.js
@@ -0,0 +1 @@
+export const globalComponents = {}
diff --git a/src/utils/object-to-formdata.js b/src/utils/object-to-formdata.js
new file mode 100644
index 0000000..47c97cd
--- /dev/null
+++ b/src/utils/object-to-formdata.js
@@ -0,0 +1,67 @@
+const isUndefined = (value) => value === undefined
+const isNull = (value) => value === null
+const isBoolean = (value) => typeof value === 'boolean'
+const isObject = (value) => value === Object(value)
+const isArray = (value) => Array.isArray(value)
+const isDate = (value) => value instanceof Date
+
+const isBlob = (value) =>
+ value &&
+ typeof value.size === 'number' &&
+ typeof value.type === 'string' &&
+ typeof value.slice === 'function'
+
+const isFile = (value) =>
+ isBlob(value) &&
+ typeof value.name === 'string' &&
+ (typeof value.lastModifiedDate === 'object' || typeof value.lastModified === 'number')
+
+export const objectToFormData = (obj, cfg = {}, fd, pre) => {
+ const config = {
+ indices: isUndefined(cfg.indices) ? true : cfg.indices,
+ nullsAsUndefineds: isUndefined(cfg.nullsAsUndefineds) ? false : cfg.nullsAsUndefineds,
+ booleansAsIntegers: isUndefined(cfg.booleansAsIntegers) ? false : cfg.booleansAsIntegers,
+ allowEmptyArrays: isUndefined(cfg.allowEmptyArrays) ? true : cfg.allowEmptyArrays,
+ }
+
+ const formData = fd || new FormData()
+
+ if (isUndefined(obj)) {
+ return formData
+ }
+
+ if (isNull(obj)) {
+ if (!config.nullsAsUndefineds) {
+ formData.append(pre, '')
+ }
+ } else if (isBoolean(obj)) {
+ formData.append(pre, config.booleansAsIntegers ? (obj ? 1 : 0) : obj)
+ } else if (isArray(obj)) {
+ if (obj.length > 0) {
+ obj.forEach((value, index) => {
+ const key = `${pre}[${config.indices ? index : ''}]`
+ objectToFormData(value, config, formData, key)
+ })
+ } else if (config.allowEmptyArrays) {
+ formData.append(pre, [])
+ }
+ } else if (isDate(obj)) {
+ formData.append(pre, obj.toISOString())
+ } else if (isObject(obj) && !isFile(obj) && !isBlob(obj)) {
+ Object.keys(obj).forEach((rawProp) => {
+ const value = obj[rawProp]
+ let prop = rawProp
+ if (isArray(value)) {
+ while (prop.length > 2 && prop.lastIndexOf('[]') === prop.length - 2) {
+ prop = prop.slice(0, Math.max(0, prop.length - 2))
+ }
+ }
+ const key = pre ? `${pre}[${prop}]` : prop
+ objectToFormData(value, config, formData, key)
+ })
+ } else {
+ formData.append(pre, obj)
+ }
+
+ return formData
+}
diff --git a/src/utils/yup-locale.js b/src/utils/yup-locale.js
new file mode 100644
index 0000000..3b75fa1
--- /dev/null
+++ b/src/utils/yup-locale.js
@@ -0,0 +1,22 @@
+import { setLocale } from 'yup'
+
+import { fields } from '@/constants/fields'
+
+const label = (path) => fields[path] || path
+
+setLocale({
+ mixed: {
+ required: ({ path }) => `فیلد ${label(path)} ضروری است`,
+ },
+ string: {
+ min: ({ path, min }) => `فیلد ${label(path)} باید حداقل ${min} کاراکتر باشد`,
+ max: ({ path, max }) => `فیلد ${label(path)} باید حداکثر ${max} کاراکتر باشد`,
+ email: ({ path }) => `فیلد ${label(path)} باید یک ایمیل معتبر باشد`,
+ url: ({ path }) => `فیلد ${label(path)} باید یک URL معتبر باشد`,
+ length: ({ path, length }) => `فیلد ${label(path)} باید دقیقا ${length} کاراکتر باشد`,
+ },
+ array: {
+ min: ({ path, min }) => `فیلد ${label(path)} باید حداقل ${min} آیتم داشته باشد`,
+ max: ({ path, max }) => `فیلد ${label(path)} باید حداکثر ${max} آیتم داشته باشد`,
+ },
+})
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..0461b9e
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,23 @@
+import { fileURLToPath, URL } from 'node:url'
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import svgLoader from 'vite-svg-loader'
+
+export default defineConfig({
+ plugins: [vue(), svgLoader()],
+ envPrefix: 'VITE',
+ css: {
+ preprocessorOptions: {
+ scss: {
+ api: 'modern-compiler',
+ },
+ },
+ },
+ resolve: {
+ extensions: ['.mjs', '.js', '.json', '.vue'],
+ alias: {
+ '@': fileURLToPath(new URL('src', import.meta.url)),
+ },
+ mainFields: ['browser', 'module', 'main', 'jsnext:main', 'jsnext'],
+ },
+})