From bc274c0e0b6c040e6afeca46b14458728b8dac83 Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Tue, 18 Nov 2025 14:01:00 +0100 Subject: [PATCH 01/13] providing statistic data in statistic component --- package-lock.json | 284 +++++++++---------- package.json | 2 +- src/app/app-module.ts | 2 + src/app/app-routing-module.ts | 7 + src/app/http.service.ts | 31 +- src/app/navbar/navbar.component.ts | 1 + src/app/statistics/statistics.component.css | 0 src/app/statistics/statistics.component.html | 6 + src/app/statistics/statistics.component.ts | 38 +++ 9 files changed, 212 insertions(+), 159 deletions(-) create mode 100644 src/app/statistics/statistics.component.css create mode 100644 src/app/statistics/statistics.component.html create mode 100644 src/app/statistics/statistics.component.ts diff --git a/package-lock.json b/package-lock.json index d26398e..1d2ab91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@angular/material": "^20.2.9", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", - "@infinimotion/model-frontend": "^0.0.102", + "@infinimotion/model-frontend": "^0.0.110", "@tailwindcss/postcss": "^4.1.14", "angularx-qrcode": "^20.0.0", "canvas-confetti": "^1.9.4", @@ -277,13 +277,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2003.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2003.9.tgz", - "integrity": "sha512-p0GO2H8hiZjRHI9sm4tXTF3OpWaEnkqvB0GBGJfGp8RvpPfDA2t3j2NAUNtd75H+B0xdfyWLmNq9YJGpy6gznA==", + "version": "0.2003.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2003.10.tgz", + "integrity": "sha512-2SWetxJzS8gRX6OKQstkWx37VRvZVgcEBDLsDSaeTjpnwh81A+niZQjAVRdwL0NEt1Wixk/RxfeUuCmdyyHvhQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.3.9", + "@angular-devkit/core": "20.3.10", "rxjs": "7.8.2" }, "engines": { @@ -293,9 +293,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "20.3.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.9.tgz", - "integrity": "sha512-bXsAGIUb4p60x548YmvnMvjwd3FwWz6re1uTM7dV0XH8nQn3XMhOQ3Q3sAckzJHxkDuaRhB3K/a4kupoOmVfTQ==", + "version": "20.3.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.3.10.tgz", + "integrity": "sha512-COOT2eVebDwHhwENk12VR6m0wjL8D7p0dncEHF15zaBt1IXEnVhGESjSrs5klnPnt5T55qCBKyCTaeK7i/cS8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -321,13 +321,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "20.3.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.3.9.tgz", - "integrity": "sha512-oaIjAKPmHMZBTC0met5M7dbXBeZnCNwmHacT/kBHNVBAz/NI95fuAfb2P0Jxt7gWdQXejDSxWp0tL+sZIyO0xw==", + "version": "20.3.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.3.10.tgz", + "integrity": "sha512-2N2WF9lj+kr3uCG4+vFadYCL5hAT4dxMgzwScSdOqSd0O+GZD0CzKbDzlfvWIWC/ZealC5Sh4dFEQaRfmy72xA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.3.9", + "@angular-devkit/core": "20.3.10", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "8.2.0", @@ -340,14 +340,14 @@ } }, "node_modules/@angular/build": { - "version": "20.3.9", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.9.tgz", - "integrity": "sha512-Ulimvg6twPSCraaZECEmENfKBlD4M1yqeHlg6dCzFNM4xcwaGUnuG6O3cIQD59DaEvaG73ceM2y8ftYdxAwFow==", + "version": "20.3.10", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.3.10.tgz", + "integrity": "sha512-nQrj1nMNZygYDilThc7hPrD6/NIWF/BOSgMfE4VkXQp8d0QronP3HFJ/h77MeoughMRFRhix0pqQSlXJQ2SGTQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2003.9", + "@angular-devkit/architect": "0.2003.10", "@babel/core": "7.28.3", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", @@ -389,7 +389,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.3.9", + "@angular/ssr": "^20.3.10", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^20.0.0", @@ -439,11 +439,10 @@ } }, "node_modules/@angular/cdk": { - "version": "20.2.12", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.2.12.tgz", - "integrity": "sha512-hz8GtiMy3N9/e8407ZfrByHD5GEC4SkWtxyUknWuTM9P88AOie0jDZ6CfQg9gQ0OJX+6BAbJV3RpYZA1uzNUqA==", + "version": "20.2.13", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.2.13.tgz", + "integrity": "sha512-h1jTkCmJ/rEQQMkxgKFMCBOrMfjZEnppgdekNmSTerwdVp4vdosTDTzFH/kwiOGFeRClffmvqQ2XLG8mQOKOtA==", "license": "MIT", - "peer": true, "dependencies": { "parse5": "^8.0.0", "tslib": "^2.3.0" @@ -455,19 +454,19 @@ } }, "node_modules/@angular/cli": { - "version": "20.3.9", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.3.9.tgz", - "integrity": "sha512-4eKpRDg96B20yrKJqjA24zgxYy1RiRd70FvF/KG1hqSowsWwtzydtEJ3VM6iFWS9t1D8truuVpKjMEnn1Y274A==", + "version": "20.3.10", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.3.10.tgz", + "integrity": "sha512-CQzXScurBXSuMMn0jf6UYDItdggaM3bHYERKL4cUG1z5JqSozVFin1+TB1EjWYkddwdgC10R5xQurdMb+ahRNw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2003.9", - "@angular-devkit/core": "20.3.9", - "@angular-devkit/schematics": "20.3.9", + "@angular-devkit/architect": "0.2003.10", + "@angular-devkit/core": "20.3.10", + "@angular-devkit/schematics": "20.3.10", "@inquirer/prompts": "7.8.2", "@listr2/prompt-adapter-inquirer": "3.0.1", "@modelcontextprotocol/sdk": "1.17.3", - "@schematics/angular": "20.3.9", + "@schematics/angular": "20.3.10", "@yarnpkg/lockfile": "1.1.0", "algoliasearch": "5.35.0", "ini": "5.0.0", @@ -490,11 +489,10 @@ } }, "node_modules/@angular/common": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.3.10.tgz", - "integrity": "sha512-12fEzvKbEqjqy1fSk9DMYlJz6dF1MJVXuC5BB+oWWJpd+2lfh4xJ62pkvvLGAICI89hfM5n9Cy5kWnXwnqPZsA==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.3.12.tgz", + "integrity": "sha512-rFcDfe67ffrb435C6t2lc27WGbizeOcgce30tUhH0iezwEvU+kHHWezXXX6Ylx3TFgqGkhcxL0fliuFYrpM1Vw==", "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -502,16 +500,15 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "20.3.10", + "@angular/core": "20.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.3.10.tgz", - "integrity": "sha512-cW939Lr8GZjPSYfbQKIDNrUaHWmn2M+zBbERThfq5skLuY+xM60bJFv4NqBekfX6YqKLCY62ilUZlnImYIXaqA==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.3.12.tgz", + "integrity": "sha512-bGESKz97nWiEQ/sydTq/Lzv3zlLvDb8t0msLG5Xti7Ch1EdLddXS8d2D/zFsjiGbAUKVsT6RgPCLHYoi4ocbhA==", "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -520,12 +517,11 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.3.10.tgz", - "integrity": "sha512-9BemvpFxA26yIVdu8ROffadMkEdlk/AQQ2Jb486w7RPkrvUQ0pbEJukhv9aryJvhbMopT66S5H/j4ipOUMzmzQ==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.3.12.tgz", + "integrity": "sha512-3SJkexqsydYjIs0iLiJr5AdwkvumpzvjJM6s76iaxXHkRll5k/vM0wqkXLlSIwieBrecO9D4J73lDLWDevXl5A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "7.28.3", "@jridgewell/sourcemap-codec": "^1.4.14", @@ -544,7 +540,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.3.10", + "@angular/compiler": "20.3.12", "typescript": ">=5.8 <6.0" }, "peerDependenciesMeta": { @@ -554,11 +550,10 @@ } }, "node_modules/@angular/core": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.3.10.tgz", - "integrity": "sha512-g99Qe+NOVo72OLxowVF9NjCckswWYHmvO7MgeiZTDJbTjF9tXH96dMx7AWq76/GUinV10sNzDysVW16NoAbCRQ==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.3.12.tgz", + "integrity": "sha512-K7vibMr55a7+EsuDhkg4Pk+ELuMm12olllwqL/CiQUcHXZ9Zgc4KYGTUuxWB69qJCG90gdSZS7tm5Dx0wDcyjg==", "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -566,7 +561,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.3.10", + "@angular/compiler": "20.3.12", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" }, @@ -580,11 +575,10 @@ } }, "node_modules/@angular/forms": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.3.10.tgz", - "integrity": "sha512-9yWr51EUauTEINB745AaHwZNTHLpXIm4uxuykxzOg+g2QskEgVfH26uS8G2ogdNuwYpB8wnsXWr34qhM3qgOWw==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.3.12.tgz", + "integrity": "sha512-O0Jy8ScaN3qVipDfR4s0SIxGrz/+MbCdmR05ZYVWf1W5P3dvETKt9WNjX9fYYV47GdgSveyFjuCR2NvWlv94zA==", "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -592,22 +586,22 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.3.10", - "@angular/core": "20.3.10", - "@angular/platform-browser": "20.3.10", + "@angular/common": "20.3.12", + "@angular/core": "20.3.12", + "@angular/platform-browser": "20.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/material": { - "version": "20.2.12", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.2.12.tgz", - "integrity": "sha512-DVenIZmV87qhDBlI2Xv3Z+b+IFI1s4wcZsFrzDi1FBMxKLsltJwMHf4SAmuqY0Mm/2Vw7HEZlfE130TuqjG8Ig==", + "version": "20.2.13", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.2.13.tgz", + "integrity": "sha512-9pjp2mULOxojYzOO7qdqt/gSVLrpYBwsIM3K0fxp+mNEcJgNjIxvmRKx46LY9+v0yrPY9puoQvP/T2C+o1+xsw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "20.2.12", + "@angular/cdk": "20.2.13", "@angular/common": "^20.0.0 || ^21.0.0", "@angular/core": "^20.0.0 || ^21.0.0", "@angular/forms": "^20.0.0 || ^21.0.0", @@ -616,11 +610,10 @@ } }, "node_modules/@angular/platform-browser": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.3.10.tgz", - "integrity": "sha512-UV8CGoB5P3FmJciI3/I/n3L7C3NVgGh7bIlZ1BaB/qJDtv0Wq0rRAGwmT/Z3gwmrRtfHZWme7/CeQ2CYJmMyUQ==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.3.12.tgz", + "integrity": "sha512-14KQsXZyaQhbRwFz1W58CtbXQc9L+mfuHBgwQjQo99422Yk0ye5WVMb6DHH7dH671qFVqL0XL7zdOPBebaAnJQ==", "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -628,9 +621,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "20.3.10", - "@angular/common": "20.3.10", - "@angular/core": "20.3.10" + "@angular/animations": "20.3.12", + "@angular/common": "20.3.12", + "@angular/core": "20.3.12" }, "peerDependenciesMeta": { "@angular/animations": { @@ -639,9 +632,9 @@ } }, "node_modules/@angular/router": { - "version": "20.3.10", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.3.10.tgz", - "integrity": "sha512-Z03cfH1jgQ7XMDJj4R8qAGqivcvhdG3wYBwaiN1K1ODBgPhbFKNeD4stKqYp7xBNtswmM2O2jMxrL/Djwju4Gg==", + "version": "20.3.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.3.12.tgz", + "integrity": "sha512-hUipb9JI/Euy3bdlhzkcWlw3cTyssPTVTDwSvyGxWO4i+UKATQYmxh8EDOrDYzFp6Aexiy0Hff/H8umdsn6ZdA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -650,9 +643,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.3.10", - "@angular/core": "20.3.10", - "@angular/platform-browser": "20.3.10", + "@angular/common": "20.3.12", + "@angular/core": "20.3.12", + "@angular/platform-browser": "20.3.12", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -687,7 +680,6 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1403,9 +1395,9 @@ } }, "node_modules/@infinimotion/model-frontend": { - "version": "0.0.102", - "resolved": "https://git.infinimotion.de/api/packages/infinimotion/npm/%40infinimotion%2Fmodel-frontend/-/0.0.102/model-frontend-0.0.102.tgz", - "integrity": "sha512-NJV9bSBubdOZ1GBIe9To3o/hh6AZscJcTyaZY2nGmMxH+GhtvO1AHmjhrQeRjwAKFiwZMEwEg4ktFiOAp3MTMQ==", + "version": "0.0.110", + "resolved": "https://git.infinimotion.de/api/packages/infinimotion/npm/%40infinimotion%2Fmodel-frontend/-/0.0.110/model-frontend-0.0.110.tgz", + "integrity": "sha512-MzHFDV8g2nOQ3p9UysB9HfoFzmycXIIaccN2do3gqIM9lkwsiN/htoGHr8fza9uv+OACifrDt4xp73nSy2Xf8w==", "license": "ISC" }, "node_modules/@inquirer/ansi": { @@ -1419,14 +1411,14 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.1.tgz", - "integrity": "sha512-rOcLotrptYIy59SGQhKlU0xBg1vvcVl2FdPIEclUvKHh0wo12OfGkId/01PIMJ/V+EimJ77t085YabgnQHBa5A==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" @@ -1466,9 +1458,9 @@ } }, "node_modules/@inquirer/core": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.1.tgz", - "integrity": "sha512-hzGKIkfomGFPgxKmnKEKeA+uCYBqC+TKtRx5LgyHRCrF6S2MliwRIjp3sUaWwVzMp7ZXVs8elB0Tfe682Rpg4w==", + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dev": true, "license": "MIT", "dependencies": { @@ -1476,7 +1468,7 @@ "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", - "mute-stream": "^3.0.0", + "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" @@ -1494,13 +1486,13 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.22", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.22.tgz", - "integrity": "sha512-8yYZ9TCbBKoBkzHtVNMF6PV1RJEUvMlhvmS3GxH4UvXMEHlS45jFyqFy0DU+K42jBs5slOaA78xGqqqWAx3u6A==", + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/external-editor": "^1.0.3", "@inquirer/type": "^3.0.10" }, @@ -1517,13 +1509,13 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.22.tgz", - "integrity": "sha512-9XOjCjvioLjwlq4S4yXzhvBmAXj5tG+jvva0uqedEsQ9VD8kZ+YT7ap23i0bIXOtow+di4+u3i6u26nDqEfY4Q==", + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, @@ -1572,13 +1564,13 @@ } }, "node_modules/@inquirer/input": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.0.tgz", - "integrity": "sha512-h4fgse5zeGsBSW3cRQqu9a99OXRdRsNCvHoBqVmz40cjYjYFzcfwD0KA96BHIPlT7rZw0IpiefQIqXrjbzjS4Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "engines": { @@ -1594,13 +1586,13 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.22.tgz", - "integrity": "sha512-oAdMJXz++fX58HsIEYmvuf5EdE8CfBHHXjoi9cTcQzgFoHGZE+8+Y3P38MlaRMeBvAVnkWtAxMUF6urL2zYsbg==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "engines": { @@ -1616,14 +1608,14 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.22", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.22.tgz", - "integrity": "sha512-CbdqK1ioIr0Y3akx03k/+Twf+KSlHjn05hBL+rmubMll7PsDTGH0R4vfFkr+XrkB0FOHrjIwVP9crt49dgt+1g==", + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "engines": { @@ -1644,7 +1636,6 @@ "integrity": "sha512-nqhDw2ZcAUrKNPwhjinJny903bRhI0rQhiDz1LksjeRxqa36i3l75+4iXbOy0rlDpLJGxqtgoPavQjmmyS5UJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@inquirer/checkbox": "^4.2.1", "@inquirer/confirm": "^5.1.14", @@ -1670,13 +1661,13 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.10.tgz", - "integrity": "sha512-Du4uidsgTMkoH5izgpfyauTL/ItVHOLsVdcY+wGeoGaG56BV+/JfmyoQGniyhegrDzXpfn3D+LFHaxMDRygcAw==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, @@ -1693,13 +1684,13 @@ } }, "node_modules/@inquirer/search": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.1.tgz", - "integrity": "sha512-cKiuUvETublmTmaOneEermfG2tI9ABpb7fW/LqzZAnSv4ZaJnbEis05lOkiBuYX5hNdnX0Q9ryOQyrNidb55WA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" @@ -1717,14 +1708,14 @@ } }, "node_modules/@inquirer/select": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.1.tgz", - "integrity": "sha512-E9hbLU4XsNe2SAOSsFrtYtYQDVi1mfbqJrPDvXKnGlnRiApBdWMJz7r3J2Ff38AqULkPUD3XjQMD4492TymD7Q==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", "dev": true, "license": "MIT", "dependencies": { "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.1", + "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" @@ -3429,14 +3420,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "20.3.9", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.3.9.tgz", - "integrity": "sha512-XkgTwGhhrx+MVi2+TFO32d6Es5Uezzx7Y7B/e2ulDlj08bizxQj+9wkeLt5+bR8JWODHpEntZn/Xd5WvXnODGA==", + "version": "20.3.10", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.3.10.tgz", + "integrity": "sha512-F9ntS2CElpoWlENf4b03nwdTcN9Ri0Nb4SAE/pfRw3In09h2UHxYyf1ex9jqQt70xltDg4wvyuc3mMs+JlSx9A==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.3.9", - "@angular-devkit/schematics": "20.3.9", + "@angular-devkit/core": "20.3.10", + "@angular-devkit/schematics": "20.3.10", "jsonc-parser": "3.3.1" }, "engines": { @@ -3865,9 +3856,9 @@ "license": "MIT" }, "node_modules/@types/jasmine": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.12.tgz", - "integrity": "sha512-1BzPxNsFDLDfj9InVR3IeY0ZVf4o9XV+4mDqoCfyPkbsA7dYyKAPAb2co6wLFlHcvxPlt1wShm7zQdV7uTfLGA==", + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.13.tgz", + "integrity": "sha512-MYCcDkruFc92LeYZux5BC0dmqo2jk+M5UIZ4/oFnAPCXN9mCcQhLyj7F3/Za7rocVyt5YRr1MmqJqFlvQ9LVcg==", "dev": true, "license": "MIT" }, @@ -3877,7 +3868,6 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -4097,9 +4087,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.8.26", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.26.tgz", - "integrity": "sha512-73lC1ugzwoaWCLJ1LvOgrR5xsMLTqSKIEoMHVtL9E/HNk0PXtTM76ZIm84856/SF7Nv8mPZxKoBsgpm0tR1u1Q==", + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.29.tgz", + "integrity": "sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4224,7 +4214,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -4412,9 +4401,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001755", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", + "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", "dev": true, "funding": [ { @@ -4992,9 +4981,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.250", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz", - "integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==", + "version": "1.5.254", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz", + "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==", "dev": true, "license": "ISC" }, @@ -5353,7 +5342,6 @@ "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", @@ -6317,8 +6305,7 @@ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.9.0.tgz", "integrity": "sha512-OMUvF1iI6+gSRYOhMrH4QYothVLN9C3EJ6wm4g7zLJlnaTl8zbaPOr0bTw70l7QxkoM7sVFOWo83u9B2Fe2Zng==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jiti": { "version": "2.6.1", @@ -6412,7 +6399,6 @@ "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -7129,7 +7115,6 @@ "integrity": "sha512-SL0JY3DaxylDuo/MecFeiC+7pedM0zia33zl0vcjgwcq1q1FWWF1To9EIauPbl8GbMCU0R2e0uJ8bZunhYKD2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -7743,13 +7728,13 @@ } }, "node_modules/mute-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", - "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, "license": "ISC", "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/nanoid": { @@ -8991,7 +8976,6 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -9048,7 +9032,6 @@ "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -9903,8 +9886,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tuf-js": { "version": "3.1.0", @@ -9942,7 +9924,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10129,7 +10110,6 @@ "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -10532,7 +10512,6 @@ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -10551,8 +10530,7 @@ "version": "0.15.1", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==", - "license": "MIT", - "peer": true + "license": "MIT" } } } diff --git a/package.json b/package.json index 955f4ce..47a9dd6 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@angular/material": "^20.2.9", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", - "@infinimotion/model-frontend": "^0.0.102", + "@infinimotion/model-frontend": "^0.0.110", "@tailwindcss/postcss": "^4.1.14", "angularx-qrcode": "^20.0.0", "canvas-confetti": "^1.9.4", diff --git a/src/app/app-module.ts b/src/app/app-module.ts index 2b87502..58a44ac 100644 --- a/src/app/app-module.ts +++ b/src/app/app-module.ts @@ -62,6 +62,7 @@ import { PurchaseSuccessComponent } from './purchase-success/purchase-success.co import { PurchaseFailedComponent } from './purchase-failed/purchase-failed.component'; import { TicketSmallComponent } from './ticket-small/ticket-small.component'; import { TicketListComponent } from './ticket-list/ticket-list.component'; +import { StatisticsComponent } from './statistics/statistics.component'; @NgModule({ @@ -105,6 +106,7 @@ import { TicketListComponent } from './ticket-list/ticket-list.component'; PurchaseFailedComponent, TicketSmallComponent, TicketListComponent, + StatisticsComponent, ], imports: [ AppRoutingModule, diff --git a/src/app/app-routing-module.ts b/src/app/app-routing-module.ts index d22e9df..178b014 100644 --- a/src/app/app-routing-module.ts +++ b/src/app/app-routing-module.ts @@ -8,6 +8,7 @@ import { ScheduleComponent } from './schedule/schedule.component'; import { TheaterOverlayComponent} from './theater-overlay/theater-overlay.component'; import { MovieImporterComponent } from './movie-importer/movie-importer.component'; import { AuthGuard } from './auth.guard'; +import {StatisticsComponent} from './statistics/statistics.component'; const routes: Routes = [ // Seiten ohne Layout @@ -28,6 +29,12 @@ const routes: Routes = [ data: { roles: ['admin'] }, // Array von erlaubten Rollen. Derzeit gäbe es 'admin' und 'employee' }, { path: 'selection/performance/:id', component: TheaterOverlayComponent}, + { + path: 'admin/statistics', + component: StatisticsComponent, + canActivate: [AuthGuard], + data: { roles: ['admin'] }, // Array von erlaubten Rollen. Derzeit gäbe es 'admin' und 'employee' + }, ], }, diff --git a/src/app/http.service.ts b/src/app/http.service.ts index d189716..5aefa63 100644 --- a/src/app/http.service.ts +++ b/src/app/http.service.ts @@ -1,4 +1,13 @@ -import { Kinosaal, Sitzplatz, Vorstellung, Film, OmdbSearch, Bestellung, Eintrittskarte } from '@infinimotion/model-frontend'; +import { + Kinosaal, + Sitzplatz, + Vorstellung, + Film, + OmdbSearch, + Bestellung, + Eintrittskarte, + StatisticsReduced, StatisticsFilm +} from '@infinimotion/model-frontend'; import { HttpClient } from "@angular/common/http"; import { inject, Injectable } from "@angular/core"; import { Observable } from "rxjs"; @@ -154,8 +163,12 @@ export class HttpService { /* Show-Seats APIs */ /* GET /api/show-seats/{show} */ - getSeatsByShowId(show: number): Observable<{seats:Sitzplatz[], reserved:Sitzplatz[], booked:Sitzplatz[]}> { - return this.http.get<{seats:Sitzplatz[], reserved:Sitzplatz[], booked:Sitzplatz[]}>(`${this.baseUrl}show-seats/${show}`); + getSeatsByShowId(show: number): Observable<{ seats: Sitzplatz[], reserved: Sitzplatz[], booked: Sitzplatz[] }> { + return this.http.get<{ + seats: Sitzplatz[], + reserved: Sitzplatz[], + booked: Sitzplatz[] + }>(`${this.baseUrl}show-seats/${show}`); } @@ -164,12 +177,20 @@ export class HttpService { /* GET /api/importer/search */ searchMovie(query: string): Observable { return this.http.get(`${this.baseUrl}importer/search`, { - params: { title: query } + params: {title: query} }); } /* POST /api/importer/import */ importMovie(imdbId: string): Observable { - return this.http.post(`${this.baseUrl}importer/import?id=${imdbId}`, {}) + return this.http.post(`${this.baseUrl}importer/import?id=${imdbId}`, {}) + } + + + /* Statistics APIs */ + + /* GET /api/statistics/list */ + getStatisticsList(): Observable { + return this.http.get(`${this.baseUrl}statistics/list`) } } diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts index 5f2de5f..8633d9c 100644 --- a/src/app/navbar/navbar.component.ts +++ b/src/app/navbar/navbar.component.ts @@ -11,6 +11,7 @@ export class NavbarComponent { navItems: { label:string, path:string }[] = [ {label: 'Programm', path: '/schedule'}, {label: 'Film importieren', path: '/admin/movie-importer'}, + {label: 'Statistiken', path: '/admin/statistics'}, ] private auth = inject(AuthService) diff --git a/src/app/statistics/statistics.component.css b/src/app/statistics/statistics.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/statistics/statistics.component.html b/src/app/statistics/statistics.component.html new file mode 100644 index 0000000..4dd5f10 --- /dev/null +++ b/src/app/statistics/statistics.component.html @@ -0,0 +1,6 @@ + diff --git a/src/app/statistics/statistics.component.ts b/src/app/statistics/statistics.component.ts new file mode 100644 index 0000000..fa82c7f --- /dev/null +++ b/src/app/statistics/statistics.component.ts @@ -0,0 +1,38 @@ +import {Component, inject} from '@angular/core'; +import {HttpService} from '../http.service'; +import { + Eintrittskarte, + Film, + StatisticsFilm, + StatisticsFilmReduced, + StatisticsReduced, StatisticsVorstellungReduced, + Vorstellung +} from '@infinimotion/model-frontend'; + +@Component({ + selector: 'app-statistics', + standalone: false, + templateUrl: './statistics.component.html', + styleUrl: './statistics.component.css', +}) +export class StatisticsComponent { + private http = inject(HttpService); + private movies: StatisticsFilmReduced[] = [] + private shows: StatisticsVorstellungReduced[] = [] + + ngOnInit(): void { + this.loadData(); + } + + loadData() { + this.http.getStatisticsList().subscribe({ + next: (response) => { + this.movies = response.movies; + this.shows = response.shows; + console.log(this.movies) + console.log(this.shows) + }, + error: (err) => console.error('Fehler beim Laden der Statistiken', err), + }); + } +} From 26f2dd21652b2f02b9cdd7b8d2496f2b7c0980fd Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:03:29 +0100 Subject: [PATCH 02/13] removed redundant ; --- src/app/order/order.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/order/order.component.ts b/src/app/order/order.component.ts index 84aa2d0..868029e 100644 --- a/src/app/order/order.component.ts +++ b/src/app/order/order.component.ts @@ -164,7 +164,7 @@ export class OrderComponent { // Tickets anlegen const tickets = seats.map(seat => { - return this.generateNewTicketObject(performance, seat, order);; + return this.generateNewTicketObject(performance, seat, order); }); // Transaktionssicher Sitzplatzbuchung From 172b0af9abd7257f1fde85966e10cca9109f9840 Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:04:20 +0100 Subject: [PATCH 03/13] add api methods for getting statistics data for movies and shows --- src/app/http.service.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/app/http.service.ts b/src/app/http.service.ts index 3a563ec..57c3684 100644 --- a/src/app/http.service.ts +++ b/src/app/http.service.ts @@ -6,7 +6,7 @@ import { OmdbSearch, Bestellung, Eintrittskarte, - StatisticsReduced, StatisticsFilm + StatisticsFilm, StatisticsVorstellung } from '@infinimotion/model-frontend'; import { HttpClient } from "@angular/common/http"; import { inject, Injectable } from "@angular/core"; @@ -195,8 +195,13 @@ export class HttpService { /* Statistics APIs */ - /* GET /api/statistics/list */ - getStatisticsList(): Observable { - return this.http.get(`${this.baseUrl}statistics/list`) + /* GET /api/statistics/movies */ + getMovieStatistics(): Observable { + return this.http.get(`${this.baseUrl}statistics/movies`) + } + + /* GET /api/statistics/shows */ + getShowStatistics(): Observable { + return this.http.get(`${this.baseUrl}statistics/shows`) } } From 0aca7ace80ca041789f0bda0832da4fa76b5494c Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:04:31 +0100 Subject: [PATCH 04/13] npm install --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d2ab91..7e96782 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@angular/material": "^20.2.9", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", - "@infinimotion/model-frontend": "^0.0.110", + "@infinimotion/model-frontend": "^0.0.116", "@tailwindcss/postcss": "^4.1.14", "angularx-qrcode": "^20.0.0", "canvas-confetti": "^1.9.4", @@ -1395,9 +1395,9 @@ } }, "node_modules/@infinimotion/model-frontend": { - "version": "0.0.110", - "resolved": "https://git.infinimotion.de/api/packages/infinimotion/npm/%40infinimotion%2Fmodel-frontend/-/0.0.110/model-frontend-0.0.110.tgz", - "integrity": "sha512-MzHFDV8g2nOQ3p9UysB9HfoFzmycXIIaccN2do3gqIM9lkwsiN/htoGHr8fza9uv+OACifrDt4xp73nSy2Xf8w==", + "version": "0.0.116", + "resolved": "https://git.infinimotion.de/api/packages/infinimotion/npm/%40infinimotion%2Fmodel-frontend/-/0.0.116/model-frontend-0.0.116.tgz", + "integrity": "sha512-kGnZW1klIHzdL/44fOEUrDTVSkQSxErgHqwuSb6eQDLUW7Q9ZDL389LFR2haJCpqcYWIjsG2HjpvkJwrm2ctpA==", "license": "ISC" }, "node_modules/@inquirer/ansi": { diff --git a/package.json b/package.json index 47a9dd6..594376e 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@angular/material": "^20.2.9", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", - "@infinimotion/model-frontend": "^0.0.110", + "@infinimotion/model-frontend": "^0.0.116", "@tailwindcss/postcss": "^4.1.14", "angularx-qrcode": "^20.0.0", "canvas-confetti": "^1.9.4", From 8ca531779566868240a850cd6e68403bdf86edfc Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:07:47 +0100 Subject: [PATCH 05/13] loading data from api asynchronously and dynamically setting page number. loading onInit --- src/app/statistics/statistics.component.ts | 49 ++++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/app/statistics/statistics.component.ts b/src/app/statistics/statistics.component.ts index fa82c7f..2c7b086 100644 --- a/src/app/statistics/statistics.component.ts +++ b/src/app/statistics/statistics.component.ts @@ -1,13 +1,11 @@ import {Component, inject} from '@angular/core'; import {HttpService} from '../http.service'; import { - Eintrittskarte, - Film, StatisticsFilm, - StatisticsFilmReduced, - StatisticsReduced, StatisticsVorstellungReduced, - Vorstellung + StatisticsVorstellung, } from '@infinimotion/model-frontend'; +import {LoadingService} from '../loading.service'; +import {firstValueFrom, forkJoin} from 'rxjs'; @Component({ selector: 'app-statistics', @@ -17,22 +15,37 @@ import { }) export class StatisticsComponent { private http = inject(HttpService); - private movies: StatisticsFilmReduced[] = [] - private shows: StatisticsVorstellungReduced[] = [] + protected movies: StatisticsFilm[] = []; + protected shows: StatisticsVorstellung[] = []; + protected moviesDisplayedColumns: string[] = ['id', 'title', 'earnings', 'tickets']; + protected showsDisplayedColumns: string[] = ['id', 'hall', 'movie_title', 'date', 'earnings', 'tickets']; + protected movieResultsLength: number = 0; + protected showsResultLength: number = 0; + + private loading = inject(LoadingService); ngOnInit(): void { - this.loadData(); + this.loading.show() + this.loadData().then(); } - loadData() { - this.http.getStatisticsList().subscribe({ - next: (response) => { - this.movies = response.movies; - this.shows = response.shows; - console.log(this.movies) - console.log(this.shows) - }, - error: (err) => console.error('Fehler beim Laden der Statistiken', err), - }); + async loadData() { + let movieRequest = this.http.getMovieStatistics(); + let showRequest = this.http.getShowStatistics(); + let movieResponse = await firstValueFrom(movieRequest); + let showResponse = await firstValueFrom(showRequest); + this.movies = movieResponse + this.shows = showResponse + if (this.movies.length / 30 < 1) { + this.movieResultsLength = 1; + } else { + this.movieResultsLength = Math.ceil(this.movies.length / 30); + } + if (this.shows.length / 30 < 1) { + this.showsResultLength = 1; + } else { + this.showsResultLength = Math.ceil(this.shows.length / 30); + } + this.loading.hide(); } } From ecb31432e11a38368607b15038b9f373bba01c2f Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:08:04 +0100 Subject: [PATCH 06/13] add helperfunction for date formating --- src/app/statistics/statistics.component.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/statistics/statistics.component.ts b/src/app/statistics/statistics.component.ts index 2c7b086..acc4b38 100644 --- a/src/app/statistics/statistics.component.ts +++ b/src/app/statistics/statistics.component.ts @@ -48,4 +48,9 @@ export class StatisticsComponent { } this.loading.hide(); } + + formatDate(date: Date) { + return new Date(date).toLocaleString("de"); + } + } From 3587af0e70dadf7bc39eca3738c78acacdd619e5 Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:08:34 +0100 Subject: [PATCH 07/13] add two tables for statistics for movies and shows --- src/app/app-module.ts | 5 ++ src/app/statistics/statistics.component.html | 91 ++++++++++++++++++-- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/app/app-module.ts b/src/app/app-module.ts index a2cab07..c0e7b03 100644 --- a/src/app/app-module.ts +++ b/src/app/app-module.ts @@ -25,6 +25,8 @@ import { MatStepperModule } from '@angular/material/stepper'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatBadgeModule } from '@angular/material/badge'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatTableModule } from '@angular/material/table'; import { HeaderComponent } from './header/header.component'; import { HomeComponent } from './home/home.component'; @@ -67,6 +69,7 @@ import { TicketListComponent } from './ticket-list/ticket-list.component'; import { StatisticsComponent } from './statistics/statistics.component'; + @NgModule({ declarations: [ App, @@ -139,6 +142,8 @@ import { StatisticsComponent } from './statistics/statistics.component'; QRCodeComponent, MatBadgeModule, MatTooltipModule, + MatPaginatorModule, + MatTableModule, ], providers: [ provideBrowserGlobalErrorListeners(), diff --git a/src/app/statistics/statistics.component.html b/src/app/statistics/statistics.component.html index 4dd5f10..4ab7190 100644 --- a/src/app/statistics/statistics.component.html +++ b/src/app/statistics/statistics.component.html @@ -1,6 +1,85 @@ - + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ID{{row.movieId}}Titel{{row.movieTitle}} + Umsatz + {{(row.earnings/100).toFixed(2)}} € + Gebuchte Tickets + {{row.tickets}}
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID{{row.showId}}Kinosaal{{row.showHallName}}Film Name{{row.movieTitle}}Datum{{formatDate(row.showStart)}} + Umsatz + {{(row.earnings/100).toFixed(2)}} € + Gebuchte Tickets + {{row.tickets}}
+
+ + + From cdf45876be120db373b21526b1530ca679208abe Mon Sep 17 00:00:00 2001 From: Marcel-Anker Date: Wed, 19 Nov 2025 11:26:01 +0100 Subject: [PATCH 08/13] =?UTF-8?q?merge=20upsi=20fix=20=F0=9F=A6=8F?= =?UTF-8?q?=F0=9F=8D=86=F0=9F=A4=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app-module.ts | 4 ++++ src/app/app-routing-module.ts | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/app/app-module.ts b/src/app/app-module.ts index 286e276..2164bb3 100644 --- a/src/app/app-module.ts +++ b/src/app/app-module.ts @@ -66,6 +66,8 @@ import { PurchaseSuccessComponent } from './purchase-success/purchase-success.co import { PurchaseFailedComponent } from './purchase-failed/purchase-failed.component'; import { TicketSmallComponent } from './ticket-small/ticket-small.component'; import { TicketListComponent } from './ticket-list/ticket-list.component'; +import { StatisticsComponent } from './statistics/statistics.component'; +import { ZoomWarningComponent } from './zoom-warning/zoom-warning.component'; @NgModule({ @@ -109,6 +111,8 @@ import { TicketListComponent } from './ticket-list/ticket-list.component'; PurchaseFailedComponent, TicketSmallComponent, TicketListComponent, + StatisticsComponent, + ZoomWarningComponent, ], imports: [ AppRoutingModule, diff --git a/src/app/app-routing-module.ts b/src/app/app-routing-module.ts index 2c6fe8a..83cb4e7 100644 --- a/src/app/app-routing-module.ts +++ b/src/app/app-routing-module.ts @@ -28,7 +28,13 @@ const routes: Routes = [ canActivate: [AuthGuard], data: { roles: ['admin'] }, // Array von erlaubten Rollen. Derzeit gäbe es 'admin' und 'employee' }, - { path: 'selection/performance/:id', component: TheaterOverlayComponent}, + { path: 'performance/:performanceId/checkout', component: TheaterOverlayComponent}, + { + path: 'admin/statistics', + component: StatisticsComponent, + canActivate: [AuthGuard], + data: { roles: ['admin'] }, // Array von erlaubten Rollen. Derzeit gäbe es 'admin' und 'employee' + }, ], }, From 1ef223c19928f832b0792677e5c184a123428a1b Mon Sep 17 00:00:00 2001 From: Lennart Heinrich Date: Wed, 19 Nov 2025 11:33:59 +0100 Subject: [PATCH 09/13] increase angular size budget --- angular.json | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/angular.json b/angular.json index 735b501..66beaba 100644 --- a/angular.json +++ b/angular.json @@ -31,9 +31,7 @@ "builder": "@angular/build:application", "options": { "browser": "src/main.ts", - "polyfills": [ - "zone.js" - ], + "polyfills": ["zone.js"], "tsConfig": "tsconfig.app.json", "inlineStyleLanguage": "css", "assets": [ @@ -47,23 +45,20 @@ "output": "assets" } ], - "styles": [ - "src/custom-theme.scss", - "src/styles.css" - ] + "styles": ["src/custom-theme.scss", "src/styles.css"] }, "configurations": { "production": { "budgets": [ { "type": "initial", - "maximumWarning": "500kB", - "maximumError": "1MB" + "maximumWarning": "5MB", + "maximumError": "10MB" }, { "type": "anyComponentStyle", - "maximumWarning": "4kB", - "maximumError": "8kB" + "maximumWarning": "100kB", + "maximumError": "500kB" } ], "outputHashing": "all" @@ -94,10 +89,7 @@ "test": { "builder": "@angular/build:karma", "options": { - "polyfills": [ - "zone.js", - "zone.js/testing" - ], + "polyfills": ["zone.js", "zone.js/testing"], "tsConfig": "tsconfig.spec.json", "inlineStyleLanguage": "css", "assets": [ @@ -106,9 +98,7 @@ "input": "public" } ], - "styles": [ - "src/styles.css" - ] + "styles": ["src/styles.css"] } } } From f37d9b44787dd6ecb42fb6f0202c5c53fdf1d907 Mon Sep 17 00:00:00 2001 From: Kevin Szarafin Date: Wed, 19 Nov 2025 16:34:21 +0100 Subject: [PATCH 10/13] =?UTF-8?q?Pricelist=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app-module.ts | 2 + src/app/app-routing-module.ts | 2 + src/app/navbar/navbar.component.ts | 1 + src/app/pricelist/pricelist.component.css | 0 src/app/pricelist/pricelist.component.html | 99 ++++++++++++++++++++++ src/app/pricelist/pricelist.component.ts | 11 +++ 6 files changed, 115 insertions(+) create mode 100644 src/app/pricelist/pricelist.component.css create mode 100644 src/app/pricelist/pricelist.component.html create mode 100644 src/app/pricelist/pricelist.component.ts diff --git a/src/app/app-module.ts b/src/app/app-module.ts index 2b87502..0c4640a 100644 --- a/src/app/app-module.ts +++ b/src/app/app-module.ts @@ -62,6 +62,7 @@ import { PurchaseSuccessComponent } from './purchase-success/purchase-success.co import { PurchaseFailedComponent } from './purchase-failed/purchase-failed.component'; import { TicketSmallComponent } from './ticket-small/ticket-small.component'; import { TicketListComponent } from './ticket-list/ticket-list.component'; +import { PricelistComponent } from './pricelist/pricelist.component'; @NgModule({ @@ -105,6 +106,7 @@ import { TicketListComponent } from './ticket-list/ticket-list.component'; PurchaseFailedComponent, TicketSmallComponent, TicketListComponent, + PricelistComponent, ], imports: [ AppRoutingModule, diff --git a/src/app/app-routing-module.ts b/src/app/app-routing-module.ts index d22e9df..484a4b7 100644 --- a/src/app/app-routing-module.ts +++ b/src/app/app-routing-module.ts @@ -8,6 +8,7 @@ import { ScheduleComponent } from './schedule/schedule.component'; import { TheaterOverlayComponent} from './theater-overlay/theater-overlay.component'; import { MovieImporterComponent } from './movie-importer/movie-importer.component'; import { AuthGuard } from './auth.guard'; +import { PricelistComponent } from './pricelist/pricelist.component'; const routes: Routes = [ // Seiten ohne Layout @@ -28,6 +29,7 @@ const routes: Routes = [ data: { roles: ['admin'] }, // Array von erlaubten Rollen. Derzeit gäbe es 'admin' und 'employee' }, { path: 'selection/performance/:id', component: TheaterOverlayComponent}, + { path: 'prices', component: PricelistComponent }, ], }, diff --git a/src/app/navbar/navbar.component.ts b/src/app/navbar/navbar.component.ts index 5f2de5f..cdf7f7a 100644 --- a/src/app/navbar/navbar.component.ts +++ b/src/app/navbar/navbar.component.ts @@ -10,6 +10,7 @@ import { Component, inject, computed, OnInit } from '@angular/core'; export class NavbarComponent { navItems: { label:string, path:string }[] = [ {label: 'Programm', path: '/schedule'}, + {label: 'Preise', path: '/prices'}, {label: 'Film importieren', path: '/admin/movie-importer'}, ] diff --git a/src/app/pricelist/pricelist.component.css b/src/app/pricelist/pricelist.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pricelist/pricelist.component.html b/src/app/pricelist/pricelist.component.html new file mode 100644 index 0000000..71b129d --- /dev/null +++ b/src/app/pricelist/pricelist.component.html @@ -0,0 +1,99 @@ + + + + + + Kino Preisliste + + + +

Kino Preisliste

+ + + + diff --git a/src/app/pricelist/pricelist.component.ts b/src/app/pricelist/pricelist.component.ts new file mode 100644 index 0000000..d359a0c --- /dev/null +++ b/src/app/pricelist/pricelist.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-pricelist', + standalone: false, + templateUrl: './pricelist.component.html', + styleUrl: './pricelist.component.css' +}) +export class PricelistComponent { + +} From 2efd78a29c513a7debb316f014b9c8e4213a9da8 Mon Sep 17 00:00:00 2001 From: Kevin Szarafin Date: Thu, 20 Nov 2025 14:13:50 +0100 Subject: [PATCH 11/13] Loading seat prices from api, layout changes not final --- src/app/http.service.ts | 11 +- src/app/pricelist/pricelist.component.css | 42 ++++++ src/app/pricelist/pricelist.component.html | 146 +++++++-------------- src/app/pricelist/pricelist.component.ts | 34 ++++- 4 files changed, 133 insertions(+), 100 deletions(-) diff --git a/src/app/http.service.ts b/src/app/http.service.ts index 57c3684..b0ad392 100644 --- a/src/app/http.service.ts +++ b/src/app/http.service.ts @@ -6,7 +6,8 @@ import { OmdbSearch, Bestellung, Eintrittskarte, - StatisticsFilm, StatisticsVorstellung + StatisticsFilm, StatisticsVorstellung, + Sitzkategorie } from '@infinimotion/model-frontend'; import { HttpClient } from "@angular/common/http"; import { inject, Injectable } from "@angular/core"; @@ -204,4 +205,12 @@ export class HttpService { getShowStatistics(): Observable { return this.http.get(`${this.baseUrl}statistics/shows`) } + + + /* Sitzkategorie APIs */ + + /* GET /api/sitzkategorie */ + getSeatCategories(): Observable { + return this.http.get(`${this.baseUrl}sitzkategorie`) + } } diff --git a/src/app/pricelist/pricelist.component.css b/src/app/pricelist/pricelist.component.css index e69de29..4b85d6c 100644 --- a/src/app/pricelist/pricelist.component.css +++ b/src/app/pricelist/pricelist.component.css @@ -0,0 +1,42 @@ +h1 { + text-align: center; + margin-bottom: 40px; + letter-spacing: 2px; +} + +.menu-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 30px; + max-width: 1000px; + margin-left: auto; + margin-right: auto; +} + +.card { + background: #faf8ff; + padding: 20px; + border-radius: 12px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.15); + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.card h2 { + margin-top: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.5); + padding-bottom: 10px; + margin-bottom: 15px; +} + +.item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + font-size: 1rem; +} + +.item:last-child { + border-bottom: none; +} diff --git a/src/app/pricelist/pricelist.component.html b/src/app/pricelist/pricelist.component.html index 71b129d..05ffe1c 100644 --- a/src/app/pricelist/pricelist.component.html +++ b/src/app/pricelist/pricelist.component.html @@ -1,99 +1,51 @@ - - - - - - Kino Preisliste - - - -

Kino Preisliste

- -