diff --git a/.gitea/workflows/auto-tag-develop.yml b/.gitea/workflows/auto-tag-develop.yml index 5bb4ac5..48f28d5 100644 --- a/.gitea/workflows/auto-tag-develop.yml +++ b/.gitea/workflows/auto-tag-develop.yml @@ -16,30 +16,50 @@ jobs: token: ${{ secrets.RELEASE_TOKEN }} persist-credentials: true - - name: Create next tag v0.0.X + - name: Create next tag from config/version.yaml shell: bash run: | set -euo pipefail - # Skip if current commit already has a v0.0.* tag - if git tag --points-at HEAD | grep -qE '^v0\.0\.'; then + # Skip if current commit already has a vX.Y.Z tag + if git tag --points-at HEAD | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then echo "Tag already exists on this commit. Skipping." exit 0 fi - last_tag="$(git tag -l 'v0.0.*' --sort=-v:refname | head -n1 || true)" - if [ -z "$last_tag" ]; then - next_tag="v0.0.1" - else - patch="${last_tag##v0.0.}" - if ! [[ "$patch" =~ ^[0-9]+$ ]]; then - echo "Unexpected tag format: $last_tag" >&2 - exit 1 - fi - next_tag="v0.0.$((patch + 1))" + changed_version=false + if git diff --name-only "${{ gitea.event.before }}" "${{ gitea.event.after }}" | grep -q '^config/version\.yaml$'; then + changed_version=true fi - git config user.name "gitea-actions" - git config user.email "gitea-actions@local" - git tag "$next_tag" - git push origin "$next_tag" + read_version() { + awk -F': *' '/app\.version:/{print $2}' config/version.yaml | tr -d '[:space:]' | tr -d "'\"" + } + + if $changed_version; then + version="$(read_version)" + if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Invalid version in version.yaml: $version" >&2 + exit 1 + fi + else + last_tag="$(git tag -l 'v*' --sort=-v:refname | head -n1 || true)" + if [ -z "$last_tag" ]; then + version="0.1.0" + else + base="${last_tag#v}" + IFS='.' read -r major minor patch <<< "$base" + version="${major}.${minor}.$((patch + 1))" + fi + + printf "parameters:\\n app.version: '%s'\\n" "$version" > config/version.yaml + git config user.name "gitea-actions" + git config user.email "gitea-actions@local" + git add config/version.yaml + git commit -m "chore: bump version to v$version" || true + git push origin develop || true + fi + + tag="v$version" + git tag "$tag" + git push origin "$tag" diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml index 9036044..531f7a7 100644 --- a/.idea/data_source_mapping.xml +++ b/.idea/data_source_mapping.xml @@ -2,5 +2,9 @@ + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 968a9a5..a3262d4 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,19 +4,11 @@ - - + - - - - - - - - - + + @@ -47,7 +39,7 @@ - + @@ -228,43 +220,43 @@ - { - "keyToString": { - "RunOnceActivity.MCP Project settings loaded": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", - "RunOnceActivity.git.unshallow": "true", - "RunOnceActivity.typescript.service.memoryLimit.init": "true", - "git-widget-placeholder": "feat/256-reception-etape-3-bovin", - "last_opened_file_path": "/home/sroy/Documents/test/Ferme", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "configurable.tailwindcss", - "ts.external.directory.path": "/opt/phpstorm/plugins/javascript-plugin/jsLanguageServicesImpl/external", - "vue.rearranger.settings.migration": "true" + +}]]> + - @@ -305,78 +297,6 @@ - - - 1768237763998 - - - - 1768237763998 - - - - 1768316052474 - - - - 1768316052474 - - - - 1768316835575 - - - - 1768316835575 - - - - 1768316965511 - - - - 1768316965511 - - - - 1768317786187 - - - - 1768317786187 - - - - 1768318875533 - - - - 1768318875533 - - - - 1768318921478 - - - - 1768318921478 - - - - 1768498751836 - - - - 1768498751836 - - - - 1768555180530 - - - - 1768555180530 - 1768832208350 @@ -697,7 +617,79 @@ 1770217875423 - + + + 1770283622425 + + + + 1770283622425 + + + + 1770308927948 + + + + 1770308927948 + + + + 1770310504254 + + + + 1770310504254 + + + + 1770369945257 + + + + 1770369945257 + + + + 1770370216428 + + + + 1770370216428 + + + + 1770370700697 + + + + 1770370700698 + + + + 1770370919043 + + + + 1770370919043 + + + + 1770371073055 + + + + 1770371073055 + + + + 1770632525875 + + + + 1770632525875 + + @@ -747,13 +739,6 @@ - - - - - - - @@ -772,18 +757,14 @@ - - - - - - - file://$PROJECT_DIR$/src/Entity/ReceptionPelletBuilding.php - 6 - - - - + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index e88d430..5902764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ Ajouter dans le fichier .env du frontend * Finalisation de la partie réception de marchandise * [#267] Lister les réceptions en attente * [#268] Lister les réceptions terminées +* [#316] Admin liste des transporteurs +* [#312] Creation administration listing fournisseurs +* [#315] Creation page admin utilisateur +* [#317] Admin modification creation transporteur ### Changed diff --git a/config/packages/security.yaml b/config/packages/security.yaml index c0859d3..35967a3 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -53,6 +53,8 @@ security: - { path: ^/api/users, roles: PUBLIC_ACCESS, methods: [GET] } # Doc API (swagger) en public - { path: ^/api/docs, roles: PUBLIC_ACCESS } + # Version de l'application en public + - { path: ^/api/version, roles: PUBLIC_ACCESS, methods: [GET] } # Tout le reste nécessite un JWT - { path: ^/, roles: IS_AUTHENTICATED_FULLY } diff --git a/config/services.yaml b/config/services.yaml index 1c52e92..5cfcb7a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,9 @@ # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration parameters: +imports: + - { resource: version.yaml } + services: # default configuration for services in *this* file _defaults: diff --git a/config/version.yaml b/config/version.yaml new file mode 100644 index 0000000..35ff19f --- /dev/null +++ b/config/version.yaml @@ -0,0 +1,2 @@ +parameters: + app.version: '0.0.36' diff --git a/frontend/app.vue b/frontend/app.vue index f8eacfa..c336825 100644 --- a/frontend/app.vue +++ b/frontend/app.vue @@ -3,3 +3,11 @@ + + diff --git a/frontend/components/user/user-form.vue b/frontend/components/user/user-form.vue new file mode 100644 index 0000000..137d299 --- /dev/null +++ b/frontend/components/user/user-form.vue @@ -0,0 +1,123 @@ + + + + + {{ userId ? "Modifications de l'utilisateur" : "Ajout d'un utilisateur" }} + + + {{ userId ? 'Sauvegarder' : 'Ajouter' }} + + + + + + + + + + + + + + diff --git a/frontend/composables/useAppVersion.ts b/frontend/composables/useAppVersion.ts new file mode 100644 index 0000000..803278d --- /dev/null +++ b/frontend/composables/useAppVersion.ts @@ -0,0 +1,17 @@ +export const useAppVersion = () => { + const api = useApi() + const version = useState('app-version', () => null) + + const load = async () => { + if (version.value) { + return version.value + } + const response = await api.get<{ version: string }>('version', {}, { + toast: false + }) + version.value = response.version + return version.value + } + + return { version, load } +} diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index cc66034..4ea1b99 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -46,7 +46,11 @@ "list": "Impossible de récupérer la liste des races de bovins." }, "carrier": { - "list": "Impossible de récupérer la liste des transporteurs." + "list": "Impossible de récupérer la liste des transporteurs.", + "fetch": "Impossible de récupérer les données du transporteur", + "update": "Impossible de mettre à jour le transporteur", + "create": "Impossible de créer le transporteur" + }, "driver": { "list": "Impossible de récupérer la liste des chauffeurs." @@ -57,7 +61,9 @@ "auth": { "login": "Identifiants invalides.", "users": "Impossible de récupérer les utilisateurs.", - "logout": "Impossible de se déconnecter." + "logout": "Impossible de se déconnecter.", + "update": "Impossible de mettre à jour l'utilisateur.", + "create": "Impossible de créer l'utilisateur." } }, "success": { @@ -65,8 +71,14 @@ "update": "Réception mise à jour avec succès." }, "auth": { + "update": "Utilisateur mis à jour avec succès.", + "create": "Utilisateur créé avec succès.", "login": "Connexion réussie.", "logout": "Déconnexion réussie." + }, + "carrier": { + "update": "Transporteur mis à jour", + "create": "Transporteur créé" } } } diff --git a/frontend/layouts/admin.vue b/frontend/layouts/admin.vue new file mode 100644 index 0000000..b534cf4 --- /dev/null +++ b/frontend/layouts/admin.vue @@ -0,0 +1,74 @@ + + + + + + + + LOGO + + + + + + + Quitter le panel admin + + + + + + + + + + + + + + + + + + diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue index 73ca923..5254dd3 100644 --- a/frontend/layouts/default.vue +++ b/frontend/layouts/default.vue @@ -1,15 +1,16 @@ - - - - LOGO - - - + + + + + - + - Reception + Admin + + + LOGO + + + Déconnexion + + + + + + - + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 071d6e3..52c54ac 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -77,6 +77,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1077,7 +1078,6 @@ "version": "4.12.2", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -1086,7 +1086,6 @@ "version": "0.21.1", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "peer": true, "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", @@ -1100,7 +1099,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1110,7 +1108,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1122,7 +1119,6 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "peer": true, "dependencies": { "@eslint/core": "^0.17.0" }, @@ -1134,7 +1130,6 @@ "version": "0.17.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -1146,7 +1141,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", - "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -1169,7 +1163,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1179,7 +1172,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "peer": true, "engines": { "node": ">= 4" } @@ -1188,7 +1180,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1200,7 +1191,6 @@ "version": "9.39.2", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1212,7 +1202,6 @@ "version": "2.1.7", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -1221,7 +1210,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "peer": true, "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" @@ -1234,7 +1222,6 @@ "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "peer": true, "engines": { "node": ">=18.18.0" } @@ -1243,7 +1230,6 @@ "version": "0.16.7", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "peer": true, "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" @@ -1256,7 +1242,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "peer": true, "engines": { "node": ">=12.22" }, @@ -1269,7 +1254,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "peer": true, "engines": { "node": ">=18.18" }, @@ -3044,6 +3028,7 @@ "version": "0.95.0", "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.95.0.tgz", "integrity": "sha512-Te8fE/SmiiKWIrwBwxz5Dod87uYvsbcZ9JAL5ylPg1DevyKgTkxCXnPEaewk1Su2qpfNmry5RHoN+NywWFCG+A==", + "peer": true, "dependencies": { "@oxc-project/types": "^0.95.0" }, @@ -4948,8 +4933,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "peer": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/parse-path": { "version": "7.0.3", @@ -5299,6 +5283,7 @@ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/parser": "^7.28.5", "@vue/compiler-core": "3.5.26", @@ -5496,6 +5481,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5533,7 +5519,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5906,6 +5891,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6019,6 +6005,7 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -6095,7 +6082,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "peer": true, "engines": { "node": ">=6" } @@ -6214,6 +6200,7 @@ "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "license": "MIT", + "peer": true, "dependencies": { "consola": "^3.2.3" } @@ -6824,8 +6811,7 @@ "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==", - "peer": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -7336,7 +7322,6 @@ "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -7363,7 +7348,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7373,7 +7357,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "peer": true, "engines": { "node": ">=10" }, @@ -7385,7 +7368,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -7397,7 +7379,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -7409,7 +7390,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "peer": true, "engines": { "node": ">= 4" } @@ -7418,7 +7398,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7430,7 +7409,6 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "peer": true, "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", @@ -7447,7 +7425,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -7471,7 +7448,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -7483,7 +7459,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -7581,8 +7556,7 @@ "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==", - "peer": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-fifo": { "version": "1.3.2", @@ -7609,14 +7583,12 @@ "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==", - "peer": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "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==", - "peer": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-npm-meta": { "version": "0.4.7", @@ -7657,7 +7629,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "peer": true, "dependencies": { "flat-cache": "^4.0.0" }, @@ -7687,7 +7658,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -7703,7 +7673,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "peer": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -7715,8 +7684,7 @@ "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "peer": true + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" }, "node_modules/foreground-child": { "version": "3.3.1", @@ -7983,7 +7951,6 @@ "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "peer": true, "engines": { "node": ">=18" }, @@ -8284,7 +8251,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "peer": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -8300,7 +8266,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "peer": true, "engines": { "node": ">=4" } @@ -8322,7 +8287,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "peer": true, "engines": { "node": ">=0.8.19" } @@ -8650,7 +8614,8 @@ "node_modules/izitoast": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/izitoast/-/izitoast-1.4.0.tgz", - "integrity": "sha512-Oc1X2wiQtPp39i5VpIjf3GJf5sfCtHKXZ5szx7RareyEeFLUlcEW0FSfBni28+Ul6KNKZRKzhVuWzSP4Xngh0w==" + "integrity": "sha512-Oc1X2wiQtPp39i5VpIjf3GJf5sfCtHKXZ5szx7RareyEeFLUlcEW0FSfBni28+Ul6KNKZRKzhVuWzSP4Xngh0w==", + "peer": true }, "node_modules/jackspeak": { "version": "3.4.3", @@ -8708,20 +8673,17 @@ "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==", - "peer": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "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==", - "peer": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "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==", - "peer": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json5": { "version": "2.2.3", @@ -8799,7 +8761,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "peer": true, "dependencies": { "json-buffer": "3.0.1" } @@ -9073,7 +9034,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -9158,7 +9118,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -9196,8 +9155,7 @@ "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==", - "peer": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.uniq": { "version": "4.5.0", @@ -9543,8 +9501,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "peer": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/negotiator": { "version": "0.6.3", @@ -10282,6 +10239,7 @@ "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.2.2.tgz", "integrity": "sha512-n6oYFikgLEb70J4+K19jAzfx4exZcRSRX7yZn09P5qlf2Z59VNOBqNmaZO5ObzvyGUZ308SZfL629/Q2v2FVjw==", "license": "MIT", + "peer": true, "dependencies": { "@dxup/nuxt": "^0.2.2", "@nuxt/cli": "^3.31.1", @@ -10549,7 +10507,6 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -10596,6 +10553,7 @@ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.102.0.tgz", "integrity": "sha512-xMiyHgr2FZsphQ12ZCsXRvSYzmKXCm1ejmyG4GDZIiKOmhyt5iKtWq0klOfFsEQ6jcgbwrUdwcCVYzr1F+h5og==", "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/types": "^0.102.0" }, @@ -10668,7 +10626,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -10683,7 +10640,6 @@ "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==", - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -10710,7 +10666,6 @@ "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==", - "peer": true, "dependencies": { "callsites": "^3.0.0" }, @@ -10759,7 +10714,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "peer": true, "engines": { "node": ">=8" } @@ -10874,6 +10828,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.7" }, @@ -10979,6 +10934,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -11528,6 +11484,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11595,7 +11552,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -11650,7 +11606,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "peer": true, "engines": { "node": ">=6" } @@ -12002,6 +11957,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -12561,7 +12517,6 @@ "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==", - "peer": true, "engines": { "node": ">=8" }, @@ -12824,6 +12779,7 @@ "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -13163,7 +13119,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -13233,6 +13188,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13674,7 +13630,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "peer": true, "dependencies": { "punycode": "^2.1.0" } @@ -13700,6 +13655,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -14056,6 +14012,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.26", "@vue/compiler-sfc": "3.5.26", @@ -14091,6 +14048,7 @@ "version": "11.2.8", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.2.8.tgz", "integrity": "sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg==", + "peer": true, "dependencies": { "@intlify/core-base": "11.2.8", "@intlify/shared": "11.2.8", @@ -14111,6 +14069,7 @@ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", "license": "MIT", + "peer": true, "dependencies": { "@vue/devtools-api": "^6.6.4" }, @@ -14162,7 +14121,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -14428,7 +14386,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "peer": true, "engines": { "node": ">=10" }, diff --git a/frontend/pages/admin/carrier/[[id]].vue b/frontend/pages/admin/carrier/[[id]].vue new file mode 100644 index 0000000..702a3f7 --- /dev/null +++ b/frontend/pages/admin/carrier/[[id]].vue @@ -0,0 +1,101 @@ + + + + + + {{ route.params.id ? 'Modifier transporteur' : 'Ajout transporteur' }} + + + Enregistrer + + + + + + + + + + + + + + diff --git a/frontend/pages/admin/carrier/carrier-list.vue b/frontend/pages/admin/carrier/carrier-list.vue new file mode 100644 index 0000000..4423186 --- /dev/null +++ b/frontend/pages/admin/carrier/carrier-list.vue @@ -0,0 +1,51 @@ + + + + listes des transporteurs + Ajouter + + + + + + Label + Code + + + {{ carrier.name}} + {{ carrier.code }} + + + + + + diff --git a/frontend/pages/admin/dashboard.vue b/frontend/pages/admin/dashboard.vue new file mode 100644 index 0000000..788fdd1 --- /dev/null +++ b/frontend/pages/admin/dashboard.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/frontend/pages/admin/supplier/supplier-list.vue b/frontend/pages/admin/supplier/supplier-list.vue new file mode 100644 index 0000000..7840c65 --- /dev/null +++ b/frontend/pages/admin/supplier/supplier-list.vue @@ -0,0 +1,74 @@ + + + Fournisseurs + + Ajouter + + + + + + Nom + Mail + Rue + Complément + Code Postal + Ville + + + + + + + {{ supplier.name }} + + + {{ supplier.email }} + + + {{ addr.street }} + + + {{ addr.street2 }} + + {{ addr.postalCode }} + + {{ addr.city }} + + + + + + + + + + + diff --git a/frontend/pages/admin/user/[[id]].vue b/frontend/pages/admin/user/[[id]].vue new file mode 100644 index 0000000..e048f43 --- /dev/null +++ b/frontend/pages/admin/user/[[id]].vue @@ -0,0 +1,8 @@ + + + + diff --git a/frontend/pages/admin/user/list.vue b/frontend/pages/admin/user/list.vue new file mode 100644 index 0000000..691c5e0 --- /dev/null +++ b/frontend/pages/admin/user/list.vue @@ -0,0 +1,57 @@ + + + Liste des utilisateurs + + Ajouter + + + + + + + + Username + Role + + + + {{ user.username }} + + + {{ user.roles?.join(', ') || ' ---' }} + + + + + + + + diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue index fd54a9a..b7e90a4 100644 --- a/frontend/pages/index.vue +++ b/frontend/pages/index.vue @@ -1,7 +1,7 @@ - + @@ -11,6 +11,5 @@ - diff --git a/frontend/pages/login.vue b/frontend/pages/login.vue index cc8c809..21d0c21 100644 --- a/frontend/pages/login.vue +++ b/frontend/pages/login.vue @@ -46,7 +46,8 @@ > Connexion - + v{{ version }} + @@ -57,6 +58,7 @@ import { useAuthStore } from '~/stores/auth' const router = useRouter() const auth = useAuthStore() +const { version } = useAppVersion() definePageMeta({ layout: 'auth' diff --git a/frontend/services/auth.ts b/frontend/services/auth.ts index a573dee..d244d50 100644 --- a/frontend/services/auth.ts +++ b/frontend/services/auth.ts @@ -1,5 +1,6 @@ import { useApi } from '~/composables/useApi' import type { UserData } from '~/services/dto/user-data' +import type {UserPayload} from "~/services/dto/user-data"; export async function getUsers() { const api = useApi() @@ -12,7 +13,40 @@ export async function getUsers() { return data['hydra:member'] ?? [] } +export async function getAdminUsers() { + const api = useApi() + const data = await api.get('admin/users', {}, { + toastErrorKey: 'errors.auth.users' + }) + if (Array.isArray(data)) { + return data + } + return data['hydra:member'] ?? [] +} + +export async function getUser(id: number) { + const api = useApi() + return api.get(`users/${id}`, {}, { + toastErrorKey: 'errors.auth.user' + }) +} + +export async function createUser(payload: UserPayload = {}) { + const api = useApi() + return api.post('users', payload, { + toastErrorKey: 'errors.auth.create', + toastSuccessKey : 'success.auth.create' + }) +} + +export async function updateUser(id : number, playload: UserPayload = {}){ + const api = useApi() + return api.patch(`users/${id}`, playload, { + toastErrorKey: 'errors.auth.update', + toastSuccessKey: 'success.auth.update' + }) +} export async function getCurrentUser() { const api = useApi() return api.get('me', {}, { diff --git a/frontend/services/carrier.ts b/frontend/services/carrier.ts index e7cd9c6..2ca3cf4 100644 --- a/frontend/services/carrier.ts +++ b/frontend/services/carrier.ts @@ -1,5 +1,5 @@ import { useApi } from '~/composables/useApi' -import type { CarrierData } from '~/services/dto/carrier-data' +import type {CarrierData, CarrierPayload} from "~/services/dto/carrier-data"; export type CarrierListResponse = | CarrierData[] @@ -21,3 +21,26 @@ export async function getCarrierList(): Promise { return [] } + +export async function getCarrier(id: number) { + const api = useApi() + return api.get(`carriers/${id}`, {}, { + toastErrorKey: 'errors.carrier.fetch' + }) +} + +export async function updateCarrier(id: number, payload: CarrierPayload) { + const api = useApi() + return api.patch(`carriers/${id}`, payload, { + toastErrorKey: 'errors.carrier.update', + toastSuccessKey: 'success.carrier.update' + }) +} + +export async function createCarrier(payload: CarrierPayload = {}) { + const api = useApi() + return api.post('carriers', payload, { + toastErrorKey: 'errors.carrier.create', + toastSuccessKey: 'success.carrier.update' + }) +} diff --git a/frontend/services/dto/carrier-data.ts b/frontend/services/dto/carrier-data.ts index 59cf5d8..6eb5bdb 100644 --- a/frontend/services/dto/carrier-data.ts +++ b/frontend/services/dto/carrier-data.ts @@ -3,3 +3,13 @@ export interface CarrierData { name: string code: string } + +export interface CarrierFormData { + name: string + code: string +} + +export type CarrierPayload = { + name?: string | null + code?: string +} diff --git a/frontend/services/dto/user-data.ts b/frontend/services/dto/user-data.ts index f3e33b5..3fb9206 100644 --- a/frontend/services/dto/user-data.ts +++ b/frontend/services/dto/user-data.ts @@ -1,4 +1,17 @@ export interface UserData { id: number username: string + roles: string[] +} + +export type UserPayload = { + username?: string + password?: string + roles?: string[] +} + +export type UserFormData = { + username: string + password: string + role: string } diff --git a/frontend/stores/auth.ts b/frontend/stores/auth.ts index 42ecfa4..4bd5e33 100644 --- a/frontend/stores/auth.ts +++ b/frontend/stores/auth.ts @@ -1,63 +1,80 @@ -import { defineStore } from 'pinia' -import type { UserData } from '~/services/dto/user-data' -import { getCurrentUser, login, logout } from '~/services/auth' +import {defineStore} from 'pinia' +import type {UserData} from '~/services/dto/user-data' +import {getCurrentUser, createUser, login, logout} from '~/services/auth' +import type {UserPayload} from "~/services/dto/user-data"; +import {ROLE} from '~/utils/constants' export const useAuthStore = defineStore('auth', { - state: () => ({ - user: null as UserData | null, - isLoading: false, - checked: false - }), - getters: { - isAuthenticated: (state) => Boolean(state.user) - }, - actions: { - clearSession() { - this.user = null - this.checked = true - this.isLoading = false + state: () => ({ + user: null as UserData | null, + isLoading: false, + checked: false + }), + getters: { + isAuthenticated: (state) => Boolean(state.user), + isAdmin: (state) => Boolean(state.user?.roles?.includes(ROLE[0].value)) }, - async ensureSession() { - if (this.checked) { - return this.user - } + actions: { + clearSession() { + this.user = null + this.checked = true + this.isLoading = false + }, + async ensureSession() { + if (this.checked) { + return this.user + } - this.checked = true + this.checked = true - try { - const me = await getCurrentUser() - this.user = me - return me - } catch { - this.user = null - return null - } - }, - async login(username: string, password: string) { - this.isLoading = true + try { + const me = await getCurrentUser() + this.user = me + return me + } catch { + this.user = null + return null + } + }, + async login(username: string, password: string) { + this.isLoading = true - try { - await login(username, password) - const me = await getCurrentUser() - this.user = me - this.checked = true - return me - } finally { - this.isLoading = false - } - }, - async logout() { - this.isLoading = true + try { + await login(username, password) + const me = await getCurrentUser() + this.user = me + this.checked = true + return me + } finally { + this.isLoading = false + } + }, + async createUser(payload: UserPayload = {}) { + this.isLoading = true + const result = await createUser(payload).finally(() => { + this.isLoading = false + }) + return result + }, + async updateUser(id: number, payload: UserPayload) { + this.isLoading = true + const result = await createUser(payload).finally(() => { + this.isLoading = false + }) + return result + }, + async logout() { + this.isLoading = true - try { - await logout() - } catch { - // Ignore logout errors so we can still clear local auth state. - } finally { - this.user = null - this.checked = true - this.isLoading = false - } + try { + await logout() + } catch { + // Ignore logout errors so we can still clear local auth state. + } finally { + this.user = null + this.checked = true + this.isLoading = false + } + }, } - } }) diff --git a/frontend/utils/constants.ts b/frontend/utils/constants.ts index 507b268..719b4f6 100644 --- a/frontend/utils/constants.ts +++ b/frontend/utils/constants.ts @@ -8,6 +8,10 @@ export const MERCHANDISE_TYPE_CODES = { AUTRES: 'AUTRES' } as const +export const ROLE = [ + { label: 'Administrateur', value: 'ROLE_ADMIN' }, + { label: 'Utilisateur', value: 'ROLE_USER' } +] export const SUPLLIER_CODE = { LIOT: 'LIOT' } diff --git a/src/ApiResource/AppVersion.php b/src/ApiResource/AppVersion.php new file mode 100644 index 0000000..ba3c071 --- /dev/null +++ b/src/ApiResource/AppVersion.php @@ -0,0 +1,25 @@ + ['version:read']], + provider: AppVersionProvider::class, + ), + ], +)] +final class AppVersion +{ + #[Groups(['version:read'])] + public string $version = ''; +} diff --git a/src/Entity/.gitignore b/src/Entity/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Entity/Carrier.php b/src/Entity/Carrier.php index a520eda..e2edc5b 100644 --- a/src/Entity/Carrier.php +++ b/src/Entity/Carrier.php @@ -7,6 +7,8 @@ namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Attribute\Groups; @@ -21,6 +23,15 @@ use Symfony\Component\Serializer\Attribute\Groups; new GetCollection( normalizationContext: ['groups' => ['carrier:read']], ), + new Post( + normalizationContext: ['groups' => ['carrier:read']], + denormalizationContext: ['groups' => ['carrier:write']], + ), + new Patch( + requirements: ['id' => '\d+'], + normalizationContext: ['groups' => ['carrier:read']], + denormalizationContext: ['groups' => ['carrier:write']], + ), ], security: "is_granted('ROLE_USER')", )] @@ -33,11 +44,11 @@ class Carrier private ?int $id = null; #[ORM\Column(length: 180)] - #[Groups(['carrier:read', 'driver:read', 'vehicle:read', 'reception:read', 'shipment:read'])] + #[Groups(['carrier:read', 'carrier:write', 'driver:read', 'vehicle:read', 'reception:read', 'shipment:read'])] private string $name = ''; #[ORM\Column(length: 30, nullable: true)] - #[Groups(['carrier:read', 'driver:read', 'vehicle:read', 'reception:read', 'shipment:read'])] + #[Groups(['carrier:read', 'carrier:write', 'driver:read', 'vehicle:read', 'reception:read', 'shipment:read'])] private ?string $code = null; public function getId(): ?int diff --git a/src/Entity/User.php b/src/Entity/User.php index aad9b14..13b672e 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -7,7 +7,10 @@ namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; use App\State\MeProvider; +use App\State\UserPasswordProcessor; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -28,10 +31,27 @@ use Symfony\Component\Serializer\Attribute\Groups; normalizationContext: ['groups' => ['user:read']], security: "is_granted('ROLE_USER')" ), - new GetCollection( + new Post( normalizationContext: ['groups' => ['user:read']], + denormalizationContext: ['groups' => ['user:write']], + security: "is_granted('ROLE_ADMIN')", + processor: UserPasswordProcessor::class + ), + new Patch( + normalizationContext: ['groups' => ['user:read']], + denormalizationContext: ['groups' => ['user:write']], + security: "is_granted('ROLE_ADMIN')", + processor: UserPasswordProcessor::class + ), + new GetCollection( + normalizationContext: ['groups' => ['user-login:read']], security: "is_granted('PUBLIC_ACCESS')" ), + new GetCollection( + uriTemplate: '/admin/users', + normalizationContext: ['groups' => ['user:read']], + security: "is_granted('ROLE_ADMIN')" + ), ], normalizationContext: ['groups' => ['user:read']], paginationEnabled: false @@ -41,17 +61,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] - #[Groups(['user:read', 'reception:read'])] + #[Groups(['user:read', 'user-login:read', 'reception:read'])] private ?int $id = null; #[ORM\Column(length: 180, unique: true)] - #[Groups(['user:read', 'reception:read'])] + #[Groups(['user:read', 'user:write', 'user-login:read', 'reception:read'])] private string $username = ''; #[ORM\Column(type: 'json')] + #[Groups(['user:write', 'user:read'])] private array $roles = []; #[ORM\Column] + #[Groups(['user:write'])] private string $password = ''; public function getId(): ?int diff --git a/src/State/AppVersionProvider.php b/src/State/AppVersionProvider.php new file mode 100644 index 0000000..cc65752 --- /dev/null +++ b/src/State/AppVersionProvider.php @@ -0,0 +1,26 @@ +version = $this->version; + + return $dto; + } +} diff --git a/src/State/UserPasswordProcessor.php b/src/State/UserPasswordProcessor.php new file mode 100644 index 0000000..8bbd8fb --- /dev/null +++ b/src/State/UserPasswordProcessor.php @@ -0,0 +1,40 @@ +getPassword(); + if ('' !== $plain) { + $data->setPassword($this->hasher->hashPassword( + $data, + $plain + )); + } + } + + return $this->persistProcessor->process( + $data, + $operation, + $uriVariables, + $context + ); + } +}
v{{ version }}