From 36236ac615531bbe16d3a4a8c587d90204c21b42 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Tue, 9 Dec 2025 12:55:33 +0100 Subject: [PATCH 01/48] end animation + dropdown menu --- package-lock.json | 876 +++++++++++++++++++++++++++-- package.json | 6 + src/pages/Stat/StatPage.jsx | 95 ++-- src/pages/Stat/StatPage.module.css | 246 ++++++-- src/pages/Stat/test.jsx | 26 + src/router.js | 5 + 6 files changed, 1137 insertions(+), 117 deletions(-) create mode 100644 src/pages/Stat/test.jsx diff --git a/package-lock.json b/package-lock.json index 2e4d992..7a1f6d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,14 @@ "name": "sae-front", "version": "0.0.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@floating-ui/react": "^0.27.16", + "@mui/material": "^7.3.6", + "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "react": "^19.1.1", + "react-bootstrap": "^2.10.10", "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4" @@ -49,7 +55,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -105,7 +110,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.3", @@ -139,7 +143,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -149,7 +152,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -191,7 +193,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -201,7 +202,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -235,7 +235,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.5" @@ -283,9 +282,7 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -294,7 +291,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -309,7 +305,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -328,7 +323,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -369,6 +363,167 @@ "storybook": "^0.0.0-0 || ^9.0.0 || ^9.1.0-0 || ^9.2.0-0 || ^10.0.0-0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.10", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", @@ -968,6 +1123,59 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.16", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz", + "integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.6", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1063,7 +1271,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1085,7 +1292,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1095,14 +1301,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1133,6 +1337,225 @@ "react": ">=16" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.6.tgz", + "integrity": "sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz", + "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/core-downloads-tracker": "^7.3.6", + "@mui/system": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.6", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", + "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.6.tgz", + "integrity": "sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.6.tgz", + "integrity": "sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz", + "integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/private-theming": "^7.3.6", + "@mui/styled-engine": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.9.tgz", + "integrity": "sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.6.tgz", + "integrity": "sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/types": "^7.4.9", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", + "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", + "license": "MIT" + }, "node_modules/@neoconfetti/react": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@neoconfetti/react/-/react-1.0.0.tgz", @@ -1196,6 +1619,85 @@ "dev": true, "license": "MIT" }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz", + "integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@popperjs/core": "^2.11.8", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.5.0", + "@types/warning": "^3.0.3", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.4", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/@restart/hooks": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz", + "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.38", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz", @@ -1765,6 +2267,15 @@ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", @@ -1926,11 +2437,22 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", - "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -1946,6 +2468,15 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -1953,6 +2484,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/project-service": { "version": "8.47.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", @@ -2550,6 +3087,21 @@ "node": ">=4" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2567,6 +3119,25 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2629,7 +3200,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2736,6 +3306,21 @@ } } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2779,6 +3364,31 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2805,14 +3415,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2847,7 +3455,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2874,6 +3481,16 @@ "license": "MIT", "peer": true }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2905,6 +3522,15 @@ "node": ">=14" } }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", @@ -2968,7 +3594,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -3315,6 +3940,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3389,7 +4020,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3500,7 +4130,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3509,6 +4138,15 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3530,7 +4168,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -3563,11 +4200,25 @@ "node": ">=8" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -3703,7 +4354,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3723,7 +4373,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -3739,6 +4388,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3813,6 +4468,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3840,7 +4501,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4022,7 +4682,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4062,7 +4721,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4129,7 +4787,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==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -4138,6 +4795,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4162,7 +4837,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -4189,6 +4863,15 @@ "dev": true, "license": "ISC" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -4210,7 +4893,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -4391,7 +5073,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4399,6 +5080,19 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "license": "MIT", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4439,6 +5133,37 @@ "node": ">=0.10.0" } }, + "node_modules/react-bootstrap": { + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.10.tgz", + "integrity": "sha512-gMckKUqn8aK/vCnfwoBpBVFUGT9SVQxwsYrp9yDHt0arXMamxALerliKBxr1TPbntirK/HGrUAHYbAeQTa9GHQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.9.4", + "@types/prop-types": "^15.7.12", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-chartjs-2": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz", @@ -4497,7 +5222,12 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, + "license": "MIT" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", "license": "MIT" }, "node_modules/react-refresh": { @@ -4532,6 +5262,22 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/recast": { "version": "0.23.11", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", @@ -4580,7 +5326,6 @@ "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", @@ -4601,7 +5346,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -5036,6 +5780,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5053,7 +5803,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5062,6 +5811,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz", + "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==", + "license": "MIT" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -5185,7 +5940,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/type-check": { @@ -5216,6 +5970,21 @@ "node": ">=14.17" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5468,6 +6237,15 @@ "node": ">=18" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/webpack-virtual-modules": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", @@ -5632,6 +6410,24 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 902a0fc..8cb618b 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,14 @@ "build-storybook": "storybook build" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@floating-ui/react": "^0.27.16", + "@mui/material": "^7.3.6", + "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "react": "^19.1.1", + "react-bootstrap": "^2.10.10", "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4" diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index cd75918..2003068 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,27 +1,37 @@ import React, { useState } from "react"; +import Dropdown from 'react-bootstrap/Dropdown'; import { Doughnut } from "react-chartjs-2"; import { Chart, ArcElement } from "chart.js"; import styles from "./StatPage.module.css"; import Button from "./../../components/ui/button/button"; +import { readUsedSize } from "chart.js/helpers"; +import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; -// Enregistrer les éléments nécessaires Chart.register(ArcElement); function StatPage() { const [months, setMonths] = useState(3); - + const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); const incompleteEvents = [ { title: "Événement A", tasks: "Préparation des flyers" }, { title: "Événement B", tasks: "Réservation de la salle" }, { title: "Événement C", tasks: "Communication sur les réseaux" }, + { title: "Événement D", tasks: "Communication sur les réseaux" }, + { title: "Événement E", tasks: "Communication sur les réseaux" }, + { title: "Événement F", tasks: "Communication sur les réseaux" }, + ]; const pendingMembers = [ { name: "Antoine Ordonneau" }, { name: "Giovanni Josserand" }, { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" } ]; const handleValidate = (name) => { @@ -39,8 +49,8 @@ function StatPage() { data: [participationRate, 100 - participationRate], backgroundColor: ["#1e60f9ff", "#ffffffff"], borderWidth: 0, - weight:10, - cutout: "90%", + weight: 10, + cutout: "95%", circumference: 360, rotation: -90, }, @@ -67,41 +77,60 @@ function StatPage() {
-
- - - - -
+
+ + + + + + +
-
+
-
+
{participationRate}%
-
+
diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 666a610..68aa2ec 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -6,6 +6,7 @@ box-sizing: border-box; gap: 20px; } + /* style a montrer a giovanni prcq il est + bo */ /*.glassCard { background: rgba(255, 255, 255, 0.2); @@ -27,41 +28,80 @@ display: flex; flex-direction: column; align-items: center; - height:fit-content; + height: fit-content; } .participationHeader { display: flex; align-items: center; - margin-bottom: 20px; - width: 100%; -} -.partiText{ - display: flex; - flex-direction: column; - width: 100%; -} -.participationHeader label{ - font-size:20px; + /*justify-content: center;*/ text-align: center; + margin-bottom: 0px; + width: 100%; +} +.participationHeader #months{ + text-align:center; } -.monthsDropdown { - width:25%; - border-radius: 5px; - opacity: 1; - background-color: transparent; - border:none; +.partiText { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 2%; + margin-top: 2%; + animation: slideInEvent 2s; +} + +.partiText label { + transition: all 0.3s ease; +} + + +.participationHeader label { + font-size: 20px; + text-align: right; +} +.participationHeader p{ + width:fit-content; } .chartContainer { - max-width: 80%; margin: 0 auto; position: relative; + + animation: slideEvent2 2s; } +@keyframes slideEvent2 { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} +.chartWrapper { + position: relative; + width: 100%; + height: 100%; + display: flex; + justify-content: center; +} + +.chartPercentage { + position: absolute; + top: 50%; + left: 50%; + text-align: center; + transform: translate(-50%, -50%); + font-size: 60px; + font-weight: bold; + color: #333; +} .circularProgress { width: 100%; @@ -82,7 +122,6 @@ font-family: Arial, sans-serif; } - .rightSection { width: 60%; display: flex; @@ -93,8 +132,9 @@ .rightBlock { width: 100%; } -.rightBlock>h2{ - font-size:29px; + +.rightBlock > h2 { + font-size: 29px; } .eventsContainer { @@ -102,93 +142,211 @@ flex-direction: row; gap: 10px; margin-top: 15px; + overflow-x: auto; + overflow-y: hidden; + padding-bottom: 10px; + scroll-behavior: smooth; } +/* Style de la scrollbar horizontale */ +.eventsContainer::-webkit-scrollbar { + height: 8px; +} + +.eventsContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb { + background: rgba(30, 96, 249, 0.5); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb:hover { + background: rgba(30, 96, 249, 0.7); +} .eventCard { - flex: 1; + min-width: calc((100% - 20px) / 3); + max-width: calc((100% - 20px) / 3); + flex-shrink: 0; padding: 10px; text-align: center; - padding-bottom:200px; + padding-bottom: 200px; + box-sizing: border-box; + opacity: 0; + transform: translateX(20px); + animation: slideInEvent 1s ease forwards; } -.eventCard>h3{ + +/* animation card */ +.eventCard:nth-child(1) { + animation-delay: 0s; +} + +.eventCard:nth-child(2) { + animation-delay: 0.1s; +} + +.eventCard:nth-child(3) { + animation-delay: 0.2s; +} + +.eventCard:nth-child(4) { + animation-delay: 0.3s; +} + +.eventCard:nth-child(5) { + animation-delay: 0.4s; +} + +.eventCard:nth-child(6) { + animation-delay: 0.5s; +} + + +@keyframes slideInEvent { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.eventCard > h3 { font-size: 24px; } + .membersContainer { display: flex; flex-direction: column; gap: 10px; margin-top: 15px; + max-height: 181px; + overflow-y: auto; + padding-right: 5px; + scroll-behavior: smooth; } +/* style scrollbar */ +.membersContainer.membersContainer::-webkit-scrollbar { + width: 8px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-thumb { + background: red; + border-radius: 10px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-thumb:hover { + background: rgba(125, 249, 30, 0.7); +} + +/*//////*/ .memberCard { display: flex; justify-content: space-between; align-items: center; padding: 10px; + flex-shrink: 0; + opacity: 0; + transform: translateY(20px); + animation: slideInMember 0.5s ease forwards; } -.memberCard p{ + +/* Animation différée pour chaque carte de membre */ +.memberCard:nth-child(1) { + animation-delay: 0s; +} + +.memberCard:nth-child(2) { + animation-delay: 0.1s; +} + +.memberCard:nth-child(3) { + animation-delay: 0.2s; +} + + + + +@keyframes slideInMember { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.memberCard p { font-weight: bold; font-size: 20px; } - .buttonGroup { display: flex; gap: 10px; justify-content: right; } - - - @media screen and (max-width: 760px) { .container { flex-direction: column; padding: 10px; } - + .leftBlock { width: 100%; margin-bottom: 20px; - height:fit-content; + height: fit-content; } - + .rightSection { width: 100%; } - - .eventsContainer { - flex-direction: column; - } - + + + .eventCard { width: 100%; } - + .donutChart { width: 120px; height: 120px; } - + .memberCard { flex-direction: column; align-items: flex-start; gap: 10px; - } - + .buttonGroup { width: 100%; justify-content: space-between; } - + .validateButton, .rejectButton { flex: 1; text-align: center; padding: 8px; } -} - + .membersContainer { + max-height: 300px; + } +} \ No newline at end of file diff --git a/src/pages/Stat/test.jsx b/src/pages/Stat/test.jsx new file mode 100644 index 0000000..a1b4d7d --- /dev/null +++ b/src/pages/Stat/test.jsx @@ -0,0 +1,26 @@ +import React, { useState } from "react"; +import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; + +function TestDropdown() { + const [selected, setSelected] = useState("3"); + + return ( +
+ + Mois + + +
+ ); +} + +export default TestDropdown; \ No newline at end of file diff --git a/src/router.js b/src/router.js index be0cf78..95fc3a4 100644 --- a/src/router.js +++ b/src/router.js @@ -3,6 +3,7 @@ import Layout from "./layout.jsx"; import HomePage from "./pages/Home/HomePage"; import LoginPage from "./pages/Login/LoginPage"; import StatPage from "./pages/Stat/StatPage"; +import testPage from "./pages/Stat/test.jsx" const router = createBrowserRouter([ { @@ -20,6 +21,10 @@ const router = createBrowserRouter([ { path: "/stat", Component:StatPage, + }, + { + path: "/test", + Component:testPage, } ] } From 54effa9a8a632962d0d7bc108a689975b3348884 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 10 Dec 2025 10:02:15 +0100 Subject: [PATCH 02/48] add responsive --- src/index.css | 14 ++++++- src/pages/Stat/StatPage.jsx | 26 ++++++------ src/pages/Stat/StatPage.module.css | 66 +++++++++++++++--------------- 3 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/index.css b/src/index.css index 1d2d1c2..ad4d8ba 100644 --- a/src/index.css +++ b/src/index.css @@ -43,7 +43,7 @@ body { } -.glassCard { +/*.glassCard { width: 100%; padding: 10px; height: fit-content; @@ -59,8 +59,18 @@ body { inset 0 0 8px 4px rgba(255, 255, 255, 0.4); position: relative; overflow: hidden; -} +}*/ + +/* style a montrer a giovanni prcq il est + bo */ +.glassCard { + background: rgba(255, 255, 255, 0.2); + backdrop-filter: blur(10px); + border-radius: 20px; + padding: 15px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + border: 1px solid rgba(255, 255, 255, 0.3); +} h1 { font-size: 3.2em; line-height: 1.1; diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index 2003068..9ba9412 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,4 +1,3 @@ -import React, { useState } from "react"; import Dropdown from 'react-bootstrap/Dropdown'; import { Doughnut } from "react-chartjs-2"; import { Chart, ArcElement } from "chart.js"; @@ -6,6 +5,8 @@ import styles from "./StatPage.module.css"; import Button from "./../../components/ui/button/button"; import { readUsedSize } from "chart.js/helpers"; import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; +import React, { useState, useEffect, useRef } from "react"; + Chart.register(ArcElement); @@ -13,7 +14,7 @@ function StatPage() { const [months, setMonths] = useState(3); const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); - + const incompleteEvents = [ { title: "Événement A", tasks: "Préparation des flyers" }, { title: "Événement B", tasks: "Réservation de la salle" }, @@ -21,9 +22,7 @@ function StatPage() { { title: "Événement D", tasks: "Communication sur les réseaux" }, { title: "Événement E", tasks: "Communication sur les réseaux" }, { title: "Événement F", tasks: "Communication sur les réseaux" }, - ]; - const pendingMembers = [ { name: "Antoine Ordonneau" }, { name: "Giovanni Josserand" }, @@ -37,11 +36,9 @@ function StatPage() { const handleValidate = (name) => { console.log(`Valider ${name}`); }; - const handleReject = (name) => { console.log(`Refuser ${name}`); }; - const chartData = { labels: ["Progress", "Background"], datasets: [ @@ -50,13 +47,12 @@ function StatPage() { backgroundColor: ["#1e60f9ff", "#ffffffff"], borderWidth: 0, weight: 10, - cutout: "95%", + cutout: "93%", circumference: 360, rotation: -90, }, ], }; - const chartOptions = { responsive: true, plugins: { @@ -72,23 +68,24 @@ function StatPage() { animateRotate: true, }, }; - return (
- - +
+ +
diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 68aa2ec..3491259 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -7,15 +7,7 @@ gap: 20px; } -/* style a montrer a giovanni prcq il est + bo */ -/*.glassCard { - background: rgba(255, 255, 255, 0.2); - backdrop-filter: blur(10px); - border-radius: 10px; - padding: 15px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - border: 1px solid rgba(255, 255, 255, 0.3); -}*/ + .block { border-radius: 10px; @@ -263,7 +255,6 @@ animation: slideInMember 0.5s ease forwards; } -/* Animation différée pour chaque carte de membre */ .memberCard:nth-child(1) { animation-delay: 0s; } @@ -304,49 +295,60 @@ @media screen and (max-width: 760px) { .container { flex-direction: column; - padding: 10px; + width:100%; + padding: 0 0 0 0; + /* padding: 10px;*/ } .leftBlock { width: 100%; - margin-bottom: 20px; + margin-top:20px; height: fit-content; } .rightSection { width: 100%; + margin:0 0 0 0; + margin-bottom: 15px; } - - + .rightBlock{ + width:100%; + margin-bottom: 0px; + } + + .rightBlock h2 { + font-size: 20px; +} .eventCard { width: 100%; + height:200px; + } + .eventCard h3{ + font-size:17px; } - .donutChart { width: 120px; height: 120px; } - - .memberCard { + .membersContainer { + max-height: 200px; + } + .partiText{ flex-direction: column; - align-items: flex-start; - gap: 10px; + justify-content: center; } - - .buttonGroup { - width: 100%; - justify-content: space-between; - } - - .validateButton, - .rejectButton { - flex: 1; + .partiText label{ text-align: center; - padding: 8px; + } + .formControl { + display: flex; + justify-content: center; + width: 100%; } - .membersContainer { - max-height: 300px; + .formDesign { + margin: 0 auto; + width: fit-content; } -} \ No newline at end of file + } \ No newline at end of file From 3ef08345a5f9c594d50b7cecf2ca2362a87ddea2 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 10 Dec 2025 12:03:12 +0100 Subject: [PATCH 03/48] cut into components --- .env | 1 + .../IncompleteEvent/IncompleteEvent.jsx | 29 ++ .../IncompleteEvent.module.css | 76 ++++ .../PendingMembers/PendingMembers.jsx | 46 +++ .../PendingMembers/PendingMembers.module.css | 73 ++++ src/components/chart/ParticipationChart.jsx | 90 +++++ .../chart/ParticipationChart.module.css | 86 +++++ src/pages/Stat/StatPage.jsx | 172 +-------- src/pages/Stat/StatPage.module.css | 331 +----------------- 9 files changed, 416 insertions(+), 488 deletions(-) create mode 100644 .env create mode 100644 src/components/IncompleteEvent/IncompleteEvent.jsx create mode 100644 src/components/IncompleteEvent/IncompleteEvent.module.css create mode 100644 src/components/PendingMembers/PendingMembers.jsx create mode 100644 src/components/PendingMembers/PendingMembers.module.css create mode 100644 src/components/chart/ParticipationChart.jsx create mode 100644 src/components/chart/ParticipationChart.module.css diff --git a/.env b/.env new file mode 100644 index 0000000..50dcc6e --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_API_URL=localhost:80 \ No newline at end of file diff --git a/src/components/IncompleteEvent/IncompleteEvent.jsx b/src/components/IncompleteEvent/IncompleteEvent.jsx new file mode 100644 index 0000000..84dc2a9 --- /dev/null +++ b/src/components/IncompleteEvent/IncompleteEvent.jsx @@ -0,0 +1,29 @@ +import React from "react"; +import styles from "./IncompleteEvent.module.css"; + +function IncompleteEvent() { + const incompleteEvents = [ + { title: "Événement A", tasks: "Préparation des flyers" }, + { title: "Événement B", tasks: "Réservation de la salle" }, + { title: "Événement C", tasks: "Communication sur les réseaux" }, + { title: "Événement D", tasks: "Communication sur les réseaux" }, + { title: "Événement E", tasks: "Communication sur les réseaux" }, + { title: "Événement F", tasks: "Communication sur les réseaux" }, + ]; + + return ( +
+

Événements incomplets

+
+ {incompleteEvents.map((event, index) => ( +
+

{event.title}

+

{event.tasks}

+
+ ))} +
+
+ ); +} + +export default IncompleteEvent; diff --git a/src/components/IncompleteEvent/IncompleteEvent.module.css b/src/components/IncompleteEvent/IncompleteEvent.module.css new file mode 100644 index 0000000..e56e1f1 --- /dev/null +++ b/src/components/IncompleteEvent/IncompleteEvent.module.css @@ -0,0 +1,76 @@ +.rightBlock { + width: 100%; +} + +.rightBlock > h2 { + font-size: 29px; +} + +.eventsContainer { + display: flex; + flex-direction: row; + gap: 10px; + margin-top: 15px; + overflow-x: auto; + overflow-y: hidden; + padding-bottom: 10px; + scroll-behavior: smooth; +} + +.eventsContainer::-webkit-scrollbar { + height: 8px; +} + +.eventsContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb { + background: rgba(30, 96, 249, 0.5); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb:hover { + background: rgba(30, 96, 249, 0.7); +} + +.eventCard { + min-width: calc((100% - 20px) / 3); + max-width: calc((100% - 20px) / 3); + flex-shrink: 0; + padding: 10px; + text-align: center; + padding-bottom: 200px; + box-sizing: border-box; + opacity: 0; + transform: translateX(20px); + animation: slideInEvent 1s ease forwards; +} + +.eventCard:nth-child(1) { animation-delay: 0s; } +.eventCard:nth-child(2) { animation-delay: 0.1s; } +.eventCard:nth-child(3) { animation-delay: 0.2s; } +.eventCard:nth-child(4) { animation-delay: 0.3s; } +.eventCard:nth-child(5) { animation-delay: 0.4s; } +.eventCard:nth-child(6) { animation-delay: 0.5s; } + +.eventCard > h3 { + font-size: 24px; +} + +@keyframes slideInEvent { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); } +} + +@media screen and (max-width: 760px) { + .eventCard { + width: 100%; + height: 200px; + } + + .eventCard h3 { + font-size: 17px; + } +} diff --git a/src/components/PendingMembers/PendingMembers.jsx b/src/components/PendingMembers/PendingMembers.jsx new file mode 100644 index 0000000..27dace2 --- /dev/null +++ b/src/components/PendingMembers/PendingMembers.jsx @@ -0,0 +1,46 @@ +import React from "react"; +import Button from "../ui/button/button"; +import styles from "./PendingMembers.module.css"; + +function pendingMembers() { + const pendingMembers = [ + { name: "Antoine Ordonneau" }, + { name: "Giovanni Josserand" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" } + ]; + + const handleValidate = (name) => { + console.log(`Valider ${name}`); + }; + + const handleReject = (name) => { + console.log(`Refuser ${name}`); + }; + + return ( +
+

Membres en attente de validation

+
+ {pendingMembers.map((member, index) => ( +
+

{member.name}

+
+ + +
+
+ ))} +
+
+ ); +} + +export default pendingMembers; diff --git a/src/components/PendingMembers/PendingMembers.module.css b/src/components/PendingMembers/PendingMembers.module.css new file mode 100644 index 0000000..974b925 --- /dev/null +++ b/src/components/PendingMembers/PendingMembers.module.css @@ -0,0 +1,73 @@ +.rightBlock { + width: 100%; +} + +.rightBlock > h2 { + font-size: 29px; +} + +.membersContainer { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 15px; + max-height: 181px; + overflow-y: auto; + padding-right: 5px; + scroll-behavior: smooth; +} + +.membersContainer::-webkit-scrollbar { + width: 8px; +} + +.membersContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.membersContainer::-webkit-scrollbar-thumb { + background: rgba(255, 0, 0, 0.5); + border-radius: 10px; +} + +.membersContainer::-webkit-scrollbar-thumb:hover { + background: rgba(125, 249, 30, 0.7); +} + +.memberCard { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + flex-shrink: 0; + opacity: 0; + transform: translateY(20px); + animation: slideInMember 0.5s ease forwards; +} + +.memberCard:nth-child(1) { animation-delay: 0s; } +.memberCard:nth-child(2) { animation-delay: 0.1s; } +.memberCard:nth-child(3) { animation-delay: 0.2s; } + +.memberCard p { + font-weight: bold; + font-size: 20px; +} + +.buttonGroup { + display: flex; + gap: 10px; + justify-content: right; +} + +@keyframes slideInMember { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +@media screen and (max-width: 760px) { + .membersContainer { + max-height: 200px; + } +} diff --git a/src/components/chart/ParticipationChart.jsx b/src/components/chart/ParticipationChart.jsx new file mode 100644 index 0000000..7648bf1 --- /dev/null +++ b/src/components/chart/ParticipationChart.jsx @@ -0,0 +1,90 @@ +import React, { useState } from "react"; +import { Doughnut } from "react-chartjs-2"; +import { Chart, ArcElement } from "chart.js"; +import { MenuItem, Select, FormControl } from "@mui/material"; +import styles from "./ParticipationChart.module.css"; + +Chart.register(ArcElement); + +function participationChart() { + const [selected, setSelected] = useState("3"); + const [participationRate, setParticipationRate] = useState(89); + + const chartData = { + labels: ["Progress", "Background"], + datasets: [ + { + data: [participationRate, 100 - participationRate], + backgroundColor: ["#1e60f9ff", "#ffffffff"], + borderWidth: 0, + weight: 10, + cutout: "93%", + circumference: 360, + rotation: -90, + }, + ], + }; + + const chartOptions = { + responsive: true, + plugins: { + legend: { display: false }, + tooltip: { enabled: false }, + }, + animation: { + animateScale: true, + animateRotate: true, + }, + }; + + return ( +
+
+
+ +
+ + + +
+
+
+
+
+ +
{participationRate}%
+
+
+
+ ); +} + +export default participationChart; diff --git a/src/components/chart/ParticipationChart.module.css b/src/components/chart/ParticipationChart.module.css new file mode 100644 index 0000000..9e16164 --- /dev/null +++ b/src/components/chart/ParticipationChart.module.css @@ -0,0 +1,86 @@ +.leftBlock { + width: 40%; + display: flex; + flex-direction: column; + align-items: center; + height: fit-content; +} + +.participationHeader { + display: flex; + align-items: center; + width: 100%; +} + +.partiText { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 2%; + margin-top: 2%; + animation: slideInEvent 2s; +} + +.partiText label { + font-size: 20px; + text-align: right; + transition: all 0.3s ease; +} + +.chartContainer { + max-width: 80%; + margin: 0 auto; + position: relative; + animation: slideEvent2 2s; +} + +.chartWrapper { + position: relative; + width: 100%; + height: 100%; + display: flex; + justify-content: center; +} + +.chartPercentage { + position: absolute; + top: 50%; + left: 50%; + text-align: center; + transform: translate(-50%, -50%); + font-size: 60px; + font-weight: bold; + color: #333; +} + +@keyframes slideEvent2 { + from { opacity: 0; transform: translateX(-20px); } + to { opacity: 1; transform: translateX(0); } +} + +@keyframes slideInEvent { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); } +} + +.formControl { + display: flex; + justify-content: center; + width: 100%; +} + +.formDesign { + margin: 0 auto; + width: fit-content; +} + +@media screen and (max-width: 760px) { + .partiText { + flex-direction: column; + justify-content: center; + } + + .partiText label { + text-align: center; + } +} diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index 9ba9412..c10bf37 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,172 +1,24 @@ -import Dropdown from 'react-bootstrap/Dropdown'; -import { Doughnut } from "react-chartjs-2"; -import { Chart, ArcElement } from "chart.js"; +import React, { useState } from "react"; import styles from "./StatPage.module.css"; -import Button from "./../../components/ui/button/button"; -import { readUsedSize } from "chart.js/helpers"; -import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; -import React, { useState, useEffect, useRef } from "react"; - - -Chart.register(ArcElement); +// Importez les composants avec une majuscule +import ParticipationChart from "../../components/chart/ParticipationChart.jsx"; +import IncompleteEvents from "../../components/IncompleteEvent/IncompleteEvent.jsx"; +import PendingMembers from "../../components/PendingMembers/PendingMembers.jsx"; function StatPage() { - const [months, setMonths] = useState(3); const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); - - const incompleteEvents = [ - { title: "Événement A", tasks: "Préparation des flyers" }, - { title: "Événement B", tasks: "Réservation de la salle" }, - { title: "Événement C", tasks: "Communication sur les réseaux" }, - { title: "Événement D", tasks: "Communication sur les réseaux" }, - { title: "Événement E", tasks: "Communication sur les réseaux" }, - { title: "Événement F", tasks: "Communication sur les réseaux" }, - ]; - const pendingMembers = [ - { name: "Antoine Ordonneau" }, - { name: "Giovanni Josserand" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" } - ]; - const handleValidate = (name) => { - console.log(`Valider ${name}`); - }; - const handleReject = (name) => { - console.log(`Refuser ${name}`); - }; - const chartData = { - labels: ["Progress", "Background"], - datasets: [ - { - data: [participationRate, 100 - participationRate], - backgroundColor: ["#1e60f9ff", "#ffffffff"], - borderWidth: 0, - weight: 10, - cutout: "93%", - circumference: 360, - rotation: -90, - }, - ], - }; - const chartOptions = { - responsive: true, - plugins: { - legend: { - display: false, - }, - tooltip: { - enabled: false, - }, - }, - animation: { - animateScale: true, - animateRotate: true, - }, - }; return (
-
-
-
- -
- - - -
- -
-
-
-
- -
- {participationRate}% -
-
-
-
+
-
-

Événements incomplets

-
- {incompleteEvents.map((event, index) => ( -
-

{event.title}

-

{event.tasks}

-
- ))} -
-
-
-

Membres en attente de validation

-
- {pendingMembers.map((member, index) => ( -
-

{member.name}

-
- - -
-
- ))} -
-
+ +
); diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 3491259..ced6cdf 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -7,113 +7,6 @@ gap: 20px; } - - -.block { - border-radius: 10px; - padding: 15px; - box-sizing: border-box; -} - -.leftBlock { - width: 40%; - display: flex; - flex-direction: column; - align-items: center; - height: fit-content; -} - -.participationHeader { - display: flex; - align-items: center; - /*justify-content: center;*/ - text-align: center; - margin-bottom: 0px; - width: 100%; -} -.participationHeader #months{ - text-align:center; -} - -.partiText { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 2%; - margin-top: 2%; - animation: slideInEvent 2s; -} - -.partiText label { - transition: all 0.3s ease; -} - - -.participationHeader label { - font-size: 20px; - text-align: right; -} -.participationHeader p{ - width:fit-content; -} - - -.chartContainer { - max-width: 80%; - margin: 0 auto; - position: relative; - - animation: slideEvent2 2s; -} - -@keyframes slideEvent2 { - from { - opacity: 0; - transform: translateX(-20px); - } - to { - opacity: 1; - transform: translateX(0); - } -} -.chartWrapper { - position: relative; - width: 100%; - height: 100%; - display: flex; - justify-content: center; -} - -.chartPercentage { - position: absolute; - top: 50%; - left: 50%; - text-align: center; - transform: translate(-50%, -50%); - font-size: 60px; - font-weight: bold; - color: #333; -} - -.circularProgress { - width: 100%; - height: 100%; -} - -.progressBackground { - opacity: 0.3; -} - -.progressBar { - transition: stroke-dasharray 0.5s ease; - stroke-linecap: round; -} - -.progressText { - font-weight: bold; - font-family: Arial, sans-serif; -} - .rightSection { width: 60%; display: flex; @@ -121,234 +14,16 @@ gap: 20px; } -.rightBlock { - width: 100%; -} - -.rightBlock > h2 { - font-size: 29px; -} - -.eventsContainer { - display: flex; - flex-direction: row; - gap: 10px; - margin-top: 15px; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: 10px; - scroll-behavior: smooth; -} - -/* Style de la scrollbar horizontale */ -.eventsContainer::-webkit-scrollbar { - height: 8px; -} - -.eventsContainer::-webkit-scrollbar-track { - background: rgba(0, 0, 0, 0.1); - border-radius: 10px; -} - -.eventsContainer::-webkit-scrollbar-thumb { - background: rgba(30, 96, 249, 0.5); - border-radius: 10px; -} - -.eventsContainer::-webkit-scrollbar-thumb:hover { - background: rgba(30, 96, 249, 0.7); -} - -.eventCard { - min-width: calc((100% - 20px) / 3); - max-width: calc((100% - 20px) / 3); - flex-shrink: 0; - padding: 10px; - text-align: center; - padding-bottom: 200px; - box-sizing: border-box; - opacity: 0; - transform: translateX(20px); - animation: slideInEvent 1s ease forwards; -} - -/* animation card */ -.eventCard:nth-child(1) { - animation-delay: 0s; -} - -.eventCard:nth-child(2) { - animation-delay: 0.1s; -} - -.eventCard:nth-child(3) { - animation-delay: 0.2s; -} - -.eventCard:nth-child(4) { - animation-delay: 0.3s; -} - -.eventCard:nth-child(5) { - animation-delay: 0.4s; -} - -.eventCard:nth-child(6) { - animation-delay: 0.5s; -} - - -@keyframes slideInEvent { - from { - opacity: 0; - transform: translateX(20px); - } - to { - opacity: 1; - transform: translateX(0); - } -} - -.eventCard > h3 { - font-size: 24px; -} - -.membersContainer { - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 15px; - max-height: 181px; - overflow-y: auto; - padding-right: 5px; - scroll-behavior: smooth; -} - -/* style scrollbar */ -.membersContainer.membersContainer::-webkit-scrollbar { - width: 8px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-track { - background: rgba(0, 0, 0, 0.1); - border-radius: 10px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-thumb { - background: red; - border-radius: 10px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-thumb:hover { - background: rgba(125, 249, 30, 0.7); -} - -/*//////*/ -.memberCard { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px; - flex-shrink: 0; - opacity: 0; - transform: translateY(20px); - animation: slideInMember 0.5s ease forwards; -} - -.memberCard:nth-child(1) { - animation-delay: 0s; -} - -.memberCard:nth-child(2) { - animation-delay: 0.1s; -} - -.memberCard:nth-child(3) { - animation-delay: 0.2s; -} - - - - -@keyframes slideInMember { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.memberCard p { - font-weight: bold; - font-size: 20px; -} - -.buttonGroup { - display: flex; - gap: 10px; - justify-content: right; -} - @media screen and (max-width: 760px) { .container { flex-direction: column; - width:100%; - padding: 0 0 0 0; - /* padding: 10px;*/ - } - - .leftBlock { width: 100%; - margin-top:20px; - height: fit-content; + padding: 0; } - + .rightSection { width: 100%; - margin:0 0 0 0; + margin: 0; margin-bottom: 15px; } - .rightBlock{ - width:100%; - margin-bottom: 0px; - } - - .rightBlock h2 { - font-size: 20px; } - - .eventCard { - width: 100%; - height:200px; - } - .eventCard h3{ - font-size:17px; - } - .donutChart { - width: 120px; - height: 120px; - } - .membersContainer { - max-height: 200px; - } - .partiText{ - flex-direction: column; - justify-content: center; - } - .partiText label{ - text-align: center; - } - .formControl { - display: flex; - justify-content: center; - width: 100%; - } - - .formDesign { - margin: 0 auto; - width: fit-content; - } - } \ No newline at end of file From 2dd2cd2d4b0a6902fbe3129028df6433c21f89a6 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 12:15:52 +0100 Subject: [PATCH 04/48] Disallow access to /admin if user is not admin --- src/contexts/auth/authProvider.jsx | 1 + src/pages/Stat/StatPage.jsx | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/contexts/auth/authProvider.jsx b/src/contexts/auth/authProvider.jsx index 850c3a2..5fd87ca 100644 --- a/src/contexts/auth/authProvider.jsx +++ b/src/contexts/auth/authProvider.jsx @@ -14,6 +14,7 @@ export function AuthProvider({ children }) { const u = await getUser(); setUser(u); setLoading(false); + console.log(u); })(); }, []); diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index cd75918..8124e6d 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,17 +1,26 @@ -import React, { useState } from "react"; +import React, { useState, useEffect, useContext } from "react"; import { Doughnut } from "react-chartjs-2"; import { Chart, ArcElement } from "chart.js"; import styles from "./StatPage.module.css"; import Button from "./../../components/ui/button/button"; +import { AuthContext } from "../../contexts/auth/AuthContext.js"; +import { useNavigate } from "react-router"; // Enregistrer les éléments nécessaires Chart.register(ArcElement); function StatPage() { + + const { user } = useContext(AuthContext); + const navigate = useNavigate(); + const [months, setMonths] = useState(3); - const [participationRate, setParticipationRate] = useState(89); + useEffect(() => { + if(!user.isAdmin) navigate("/") + }, []) + const incompleteEvents = [ { title: "Événement A", tasks: "Préparation des flyers" }, { title: "Événement B", tasks: "Réservation de la salle" }, From 11efe3565e12648611116423798a89f552a4b73c Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 12:23:28 +0100 Subject: [PATCH 05/48] Fix import --- src/components/SearchBar/SearchBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SearchBar/SearchBar.jsx b/src/components/SearchBar/SearchBar.jsx index d79dfde..ddd0521 100644 --- a/src/components/SearchBar/SearchBar.jsx +++ b/src/components/SearchBar/SearchBar.jsx @@ -3,7 +3,7 @@ import {Link} from "react-router"; import {useEffect, useState} from "react"; import searchEvents from "../../utils/searchEvents.js"; import searchUsers from "../../utils/searchUsers.js"; -import { useLocation } from "react-router-dom"; +import { useLocation } from "react-router"; function SearchBar() { From b710669eadf4b7ad5068618639980206f6b8549f Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 10 Dec 2025 13:57:46 +0100 Subject: [PATCH 06/48] rebase & resolve conflicts --- package-lock.json | 1687 ++++++++++++------------ package.json | 6 + src/components/SearchBar/SearchBar.jsx | 2 +- src/pages/Stat/StatPage.jsx | 95 +- src/pages/Stat/StatPage.module.css | 246 +++- src/pages/Stat/test.jsx | 26 + src/router.js | 7 +- 7 files changed, 1180 insertions(+), 889 deletions(-) create mode 100644 src/pages/Stat/test.jsx diff --git a/package-lock.json b/package-lock.json index c714a7e..b9af60f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,14 @@ "name": "sae-front", "version": "0.0.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@floating-ui/react": "^0.27.16", + "@mui/material": "^7.3.6", + "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "react": "^19.1.1", + "react-bootstrap": "^2.10.10", "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4", @@ -50,7 +56,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -106,7 +111,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.3", @@ -140,7 +144,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -150,7 +153,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -192,7 +194,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -202,7 +203,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -236,7 +236,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.5" @@ -284,9 +283,7 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -295,7 +292,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -310,7 +306,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -329,7 +324,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -370,277 +364,166 @@ "storybook": "^0.0.0-0 || ^9.0.0 || ^9.1.0-0 || ^9.2.0-0 || ^10.0.0-0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@emotion/memoize": "^0.9.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", - "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "peerDependencies": { + "react": ">=16.8.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" }, "node_modules/@esbuild/linux-x64": { "version": "0.25.10", @@ -659,159 +542,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -969,6 +699,59 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.16", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz", + "integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.6", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1064,7 +847,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1086,7 +868,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1096,14 +877,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1134,6 +913,225 @@ "react": ">=16" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.6.tgz", + "integrity": "sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz", + "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/core-downloads-tracker": "^7.3.6", + "@mui/system": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.6", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", + "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.6.tgz", + "integrity": "sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.6.tgz", + "integrity": "sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz", + "integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/private-theming": "^7.3.6", + "@mui/styled-engine": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.9.tgz", + "integrity": "sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.6.tgz", + "integrity": "sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/types": "^7.4.9", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", + "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", + "license": "MIT" + }, "node_modules/@neoconfetti/react": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@neoconfetti/react/-/react-1.0.0.tgz", @@ -1197,6 +1195,85 @@ "dev": true, "license": "MIT" }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz", + "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz", + "integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@popperjs/core": "^2.11.8", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.5.0", + "@types/warning": "^3.0.3", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.4", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/@restart/hooks": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz", + "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz", + "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.14.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.38", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz", @@ -1227,216 +1304,6 @@ } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", - "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", - "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", - "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", - "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", - "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", - "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", - "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", - "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", - "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", - "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", - "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", - "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", - "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", - "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", - "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.52.4", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", @@ -1465,76 +1332,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", - "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", - "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", - "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", - "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", - "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@standard-schema/spec": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", @@ -1766,6 +1563,15 @@ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", @@ -1927,11 +1733,22 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", - "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -1947,6 +1764,15 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -1954,6 +1780,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/warning": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz", + "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/project-service": { "version": "8.47.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", @@ -2157,14 +1989,14 @@ } }, "node_modules/@vitest/browser": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.10.tgz", - "integrity": "sha512-irO+aGxYx/rAhjEBLsGPO4JQ8dA+A43enIST0j4xQ2kYHatHi9tUcxkRRGpClGuUVU42mi+iQsFFzd4xxpoV3g==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.13.tgz", + "integrity": "sha512-lruSgrYPVAJzKmX6EJYCg9nY+0A4VkeTLpTzf1jRD/XMjNbzD9yy7D499xmVKglwJczANYJXBvZSPGcRlon+0w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/mocker": "4.0.10", - "@vitest/utils": "4.0.10", + "@vitest/mocker": "4.0.13", + "@vitest/utils": "4.0.13", "magic-string": "^0.30.21", "pixelmatch": "7.1.0", "pngjs": "^7.0.0", @@ -2176,18 +2008,18 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.0.10" + "vitest": "4.0.13" } }, "node_modules/@vitest/browser-playwright": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.10.tgz", - "integrity": "sha512-pm7Hl7BNyluox+uGJPnT7vCRDSI+ibHcWQRtnCACAZWxD6/b2gN+8pO0qTDPHpxDSTPKDS5sT2dKTHLcr+lsng==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.13.tgz", + "integrity": "sha512-oaRY+/pvwS4/sN2rE2aZh9jdli8EkXm5AidmXEbWRu2wW0omG9PmgChWCX2jsD9qRLQxXTSLl5oKezANNF6LnQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/browser": "4.0.10", - "@vitest/mocker": "4.0.10", + "@vitest/browser": "4.0.13", + "@vitest/mocker": "4.0.13", "tinyrainbow": "^3.0.3" }, "funding": { @@ -2195,7 +2027,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "4.0.10" + "vitest": "4.0.13" }, "peerDependenciesMeta": { "playwright": { @@ -2204,14 +2036,14 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.10.tgz", - "integrity": "sha512-g+brmtoKa/sAeIohNJnnWhnHtU6GuqqVOSQ4SxDIPcgZWZyhJs5RmF5LpqXs8Kq64lANP+vnbn5JLzhLj/G56g==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.13.tgz", + "integrity": "sha512-w77N6bmtJ3CFnL/YHiYotwW/JI3oDlR3K38WEIqegRfdMSScaYxwYKB/0jSNpOTZzUjQkG8HHEz4sdWQMWpQ5g==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.10", + "@vitest/utils": "4.0.13", "ast-v8-to-istanbul": "^0.3.8", "debug": "^4.4.3", "istanbul-lib-coverage": "^3.2.2", @@ -2226,8 +2058,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.0.10", - "vitest": "4.0.10" + "@vitest/browser": "4.0.13", + "vitest": "4.0.13" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2304,13 +2136,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.10.tgz", - "integrity": "sha512-e2OfdexYkjkg8Hh3L9NVEfbwGXq5IZbDovkf30qW2tOh7Rh9sVtmSr2ztEXOFbymNxS4qjzLXUQIvATvN4B+lg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.13.tgz", + "integrity": "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.10", + "@vitest/spy": "4.0.13", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -2341,9 +2173,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.10.tgz", - "integrity": "sha512-99EQbpa/zuDnvVjthwz5bH9o8iPefoQZ63WV8+bsRJZNw3qQSvSltfut8yu1Jc9mqOYi7pEbsKxYTi/rjaq6PA==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.13.tgz", + "integrity": "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA==", "dev": true, "license": "MIT", "dependencies": { @@ -2354,13 +2186,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.10.tgz", - "integrity": "sha512-EXU2iSkKvNwtlL8L8doCpkyclw0mc/t4t9SeOnfOFPyqLmQwuceMPA4zJBa6jw0MKsZYbw7kAn+gl7HxrlB8UQ==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.13.tgz", + "integrity": "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.10", + "@vitest/utils": "4.0.13", "pathe": "^2.0.3" }, "funding": { @@ -2368,13 +2200,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.10.tgz", - "integrity": "sha512-2N4X2ZZl7kZw0qeGdQ41H0KND96L3qX1RgwuCfy6oUsF2ISGD/HpSbmms+CkIOsQmg2kulwfhJ4CI0asnZlvkg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.13.tgz", + "integrity": "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.10", + "@vitest/pretty-format": "4.0.13", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2383,9 +2215,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.10.tgz", - "integrity": "sha512-AsY6sVS8OLb96GV5RoG8B6I35GAbNrC49AO+jNRF9YVGb/g9t+hzNm1H6kD0NDp8tt7VJLs6hb7YMkDXqu03iw==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.13.tgz", + "integrity": "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw==", "dev": true, "license": "MIT", "funding": { @@ -2393,13 +2225,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.10.tgz", - "integrity": "sha512-kOuqWnEwZNtQxMKg3WmPK1vmhZu9WcoX69iwWjVz+jvKTsF1emzsv3eoPcDr6ykA3qP2bsCQE7CwqfNtAVzsmg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.13.tgz", + "integrity": "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.10", + "@vitest/pretty-format": "4.0.13", "tinyrainbow": "^3.0.3" }, "funding": { @@ -2551,6 +2383,21 @@ "node": ">=4" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2568,6 +2415,25 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2630,7 +2496,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2737,6 +2602,21 @@ } } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2780,6 +2660,31 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2806,14 +2711,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2848,7 +2751,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2875,6 +2777,16 @@ "license": "MIT", "peer": true }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2906,6 +2818,15 @@ "node": ">=14" } }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", @@ -2969,7 +2890,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -3316,6 +3236,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3371,26 +3297,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3501,7 +3411,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3510,6 +3419,15 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3531,7 +3449,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -3564,11 +3481,25 @@ "node": ">=8" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -3704,7 +3635,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3724,7 +3654,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -3740,6 +3669,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3814,6 +3749,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3841,7 +3782,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4023,7 +3963,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4063,7 +4002,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4130,7 +4068,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==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -4139,6 +4076,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4163,7 +4118,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -4190,6 +4144,15 @@ "dev": true, "license": "ISC" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -4211,7 +4174,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -4272,21 +4234,6 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/pngjs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", @@ -4392,7 +4339,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4400,6 +4346,19 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "license": "MIT", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4440,6 +4399,37 @@ "node": ">=0.10.0" } }, + "node_modules/react-bootstrap": { + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.10.tgz", + "integrity": "sha512-gMckKUqn8aK/vCnfwoBpBVFUGT9SVQxwsYrp9yDHt0arXMamxALerliKBxr1TPbntirK/HGrUAHYbAeQTa9GHQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@restart/hooks": "^0.4.9", + "@restart/ui": "^1.9.4", + "@types/prop-types": "^15.7.12", + "@types/react-transition-group": "^4.4.6", + "classnames": "^2.3.2", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.5", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-chartjs-2": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz", @@ -4498,7 +4488,12 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, + "license": "MIT" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", "license": "MIT" }, "node_modules/react-refresh": { @@ -4549,6 +4544,22 @@ "react-dom": ">=18" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/recast": { "version": "0.23.11", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", @@ -4597,7 +4608,6 @@ "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", @@ -4618,7 +4628,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -5053,6 +5062,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5070,7 +5085,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -5079,6 +5093,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz", + "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==", + "license": "MIT" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -5202,7 +5222,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/type-check": { @@ -5233,6 +5252,21 @@ "node": ">=14.17" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5244,9 +5278,9 @@ } }, "node_modules/unplugin": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz", - "integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", "dev": true, "license": "MIT", "dependencies": { @@ -5376,19 +5410,19 @@ } }, "node_modules/vitest": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.10.tgz", - "integrity": "sha512-2Fqty3MM9CDwOVet/jaQalYlbcjATZwPYGcqpiYQqgQ/dLC7GuHdISKgTYIVF/kaishKxLzleKWWfbSDklyIKg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.13.tgz", + "integrity": "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.10", - "@vitest/mocker": "4.0.10", - "@vitest/pretty-format": "4.0.10", - "@vitest/runner": "4.0.10", - "@vitest/snapshot": "4.0.10", - "@vitest/spy": "4.0.10", - "@vitest/utils": "4.0.10", + "@vitest/expect": "4.0.13", + "@vitest/mocker": "4.0.13", + "@vitest/pretty-format": "4.0.13", + "@vitest/runner": "4.0.13", + "@vitest/snapshot": "4.0.13", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", @@ -5414,12 +5448,13 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.10", - "@vitest/browser-preview": "4.0.10", - "@vitest/browser-webdriverio": "4.0.10", - "@vitest/ui": "4.0.10", + "@vitest/browser-playwright": "4.0.13", + "@vitest/browser-preview": "4.0.13", + "@vitest/browser-webdriverio": "4.0.13", + "@vitest/ui": "4.0.13", "happy-dom": "*", "jsdom": "*" }, @@ -5427,6 +5462,9 @@ "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/debug": { "optional": true }, @@ -5454,16 +5492,16 @@ } }, "node_modules/vitest/node_modules/@vitest/expect": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.10.tgz", - "integrity": "sha512-3QkTX/lK39FBNwARCQRSQr0TP9+ywSdxSX+LgbJ2M1WmveXP72anTbnp2yl5fH+dU6SUmBzNMrDHs80G8G2DZg==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.13.tgz", + "integrity": "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.10", - "@vitest/utils": "4.0.10", + "@vitest/spy": "4.0.13", + "@vitest/utils": "4.0.13", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" }, @@ -5481,6 +5519,15 @@ "node": ">=18" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/webpack-virtual-modules": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", @@ -5645,6 +5692,24 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 996fc4e..7ba6610 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,14 @@ "test": "vitest" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@floating-ui/react": "^0.27.16", + "@mui/material": "^7.3.6", + "bootstrap": "^5.3.8", "chart.js": "^4.5.1", "react": "^19.1.1", + "react-bootstrap": "^2.10.10", "react-chartjs-2": "^5.3.1", "react-dom": "^19.1.1", "react-router": "^7.9.4", diff --git a/src/components/SearchBar/SearchBar.jsx b/src/components/SearchBar/SearchBar.jsx index d79dfde..ddd0521 100644 --- a/src/components/SearchBar/SearchBar.jsx +++ b/src/components/SearchBar/SearchBar.jsx @@ -3,7 +3,7 @@ import {Link} from "react-router"; import {useEffect, useState} from "react"; import searchEvents from "../../utils/searchEvents.js"; import searchUsers from "../../utils/searchUsers.js"; -import { useLocation } from "react-router-dom"; +import { useLocation } from "react-router"; function SearchBar() { diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index 8124e6d..78a212b 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,12 +1,15 @@ + import React, { useState, useEffect, useContext } from "react"; +import Dropdown from 'react-bootstrap/Dropdown'; import { Doughnut } from "react-chartjs-2"; import { Chart, ArcElement } from "chart.js"; import styles from "./StatPage.module.css"; import Button from "./../../components/ui/button/button"; import { AuthContext } from "../../contexts/auth/AuthContext.js"; import { useNavigate } from "react-router"; +import { readUsedSize } from "chart.js/helpers"; +import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; -// Enregistrer les éléments nécessaires Chart.register(ArcElement); function StatPage() { @@ -15,6 +18,7 @@ function StatPage() { const navigate = useNavigate(); const [months, setMonths] = useState(3); + const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); useEffect(() => { @@ -25,12 +29,20 @@ function StatPage() { { title: "Événement A", tasks: "Préparation des flyers" }, { title: "Événement B", tasks: "Réservation de la salle" }, { title: "Événement C", tasks: "Communication sur les réseaux" }, + { title: "Événement D", tasks: "Communication sur les réseaux" }, + { title: "Événement E", tasks: "Communication sur les réseaux" }, + { title: "Événement F", tasks: "Communication sur les réseaux" }, + ]; const pendingMembers = [ { name: "Antoine Ordonneau" }, { name: "Giovanni Josserand" }, { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" } ]; const handleValidate = (name) => { @@ -48,8 +60,8 @@ function StatPage() { data: [participationRate, 100 - participationRate], backgroundColor: ["#1e60f9ff", "#ffffffff"], borderWidth: 0, - weight:10, - cutout: "90%", + weight: 10, + cutout: "95%", circumference: 360, rotation: -90, }, @@ -76,41 +88,60 @@ function StatPage() {
-
- - - - -
+
+ + + + + + +
-
+
-
+
{participationRate}%
-
+
diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 666a610..68aa2ec 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -6,6 +6,7 @@ box-sizing: border-box; gap: 20px; } + /* style a montrer a giovanni prcq il est + bo */ /*.glassCard { background: rgba(255, 255, 255, 0.2); @@ -27,41 +28,80 @@ display: flex; flex-direction: column; align-items: center; - height:fit-content; + height: fit-content; } .participationHeader { display: flex; align-items: center; - margin-bottom: 20px; - width: 100%; -} -.partiText{ - display: flex; - flex-direction: column; - width: 100%; -} -.participationHeader label{ - font-size:20px; + /*justify-content: center;*/ text-align: center; + margin-bottom: 0px; + width: 100%; +} +.participationHeader #months{ + text-align:center; } -.monthsDropdown { - width:25%; - border-radius: 5px; - opacity: 1; - background-color: transparent; - border:none; +.partiText { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 2%; + margin-top: 2%; + animation: slideInEvent 2s; +} + +.partiText label { + transition: all 0.3s ease; +} + + +.participationHeader label { + font-size: 20px; + text-align: right; +} +.participationHeader p{ + width:fit-content; } .chartContainer { - max-width: 80%; margin: 0 auto; position: relative; + + animation: slideEvent2 2s; } +@keyframes slideEvent2 { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} +.chartWrapper { + position: relative; + width: 100%; + height: 100%; + display: flex; + justify-content: center; +} + +.chartPercentage { + position: absolute; + top: 50%; + left: 50%; + text-align: center; + transform: translate(-50%, -50%); + font-size: 60px; + font-weight: bold; + color: #333; +} .circularProgress { width: 100%; @@ -82,7 +122,6 @@ font-family: Arial, sans-serif; } - .rightSection { width: 60%; display: flex; @@ -93,8 +132,9 @@ .rightBlock { width: 100%; } -.rightBlock>h2{ - font-size:29px; + +.rightBlock > h2 { + font-size: 29px; } .eventsContainer { @@ -102,93 +142,211 @@ flex-direction: row; gap: 10px; margin-top: 15px; + overflow-x: auto; + overflow-y: hidden; + padding-bottom: 10px; + scroll-behavior: smooth; } +/* Style de la scrollbar horizontale */ +.eventsContainer::-webkit-scrollbar { + height: 8px; +} + +.eventsContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb { + background: rgba(30, 96, 249, 0.5); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb:hover { + background: rgba(30, 96, 249, 0.7); +} .eventCard { - flex: 1; + min-width: calc((100% - 20px) / 3); + max-width: calc((100% - 20px) / 3); + flex-shrink: 0; padding: 10px; text-align: center; - padding-bottom:200px; + padding-bottom: 200px; + box-sizing: border-box; + opacity: 0; + transform: translateX(20px); + animation: slideInEvent 1s ease forwards; } -.eventCard>h3{ + +/* animation card */ +.eventCard:nth-child(1) { + animation-delay: 0s; +} + +.eventCard:nth-child(2) { + animation-delay: 0.1s; +} + +.eventCard:nth-child(3) { + animation-delay: 0.2s; +} + +.eventCard:nth-child(4) { + animation-delay: 0.3s; +} + +.eventCard:nth-child(5) { + animation-delay: 0.4s; +} + +.eventCard:nth-child(6) { + animation-delay: 0.5s; +} + + +@keyframes slideInEvent { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.eventCard > h3 { font-size: 24px; } + .membersContainer { display: flex; flex-direction: column; gap: 10px; margin-top: 15px; + max-height: 181px; + overflow-y: auto; + padding-right: 5px; + scroll-behavior: smooth; } +/* style scrollbar */ +.membersContainer.membersContainer::-webkit-scrollbar { + width: 8px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-thumb { + background: red; + border-radius: 10px; +} + +.membersContainer.membersContainer::-webkit-scrollbar-thumb:hover { + background: rgba(125, 249, 30, 0.7); +} + +/*//////*/ .memberCard { display: flex; justify-content: space-between; align-items: center; padding: 10px; + flex-shrink: 0; + opacity: 0; + transform: translateY(20px); + animation: slideInMember 0.5s ease forwards; } -.memberCard p{ + +/* Animation différée pour chaque carte de membre */ +.memberCard:nth-child(1) { + animation-delay: 0s; +} + +.memberCard:nth-child(2) { + animation-delay: 0.1s; +} + +.memberCard:nth-child(3) { + animation-delay: 0.2s; +} + + + + +@keyframes slideInMember { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.memberCard p { font-weight: bold; font-size: 20px; } - .buttonGroup { display: flex; gap: 10px; justify-content: right; } - - - @media screen and (max-width: 760px) { .container { flex-direction: column; padding: 10px; } - + .leftBlock { width: 100%; margin-bottom: 20px; - height:fit-content; + height: fit-content; } - + .rightSection { width: 100%; } - - .eventsContainer { - flex-direction: column; - } - + + + .eventCard { width: 100%; } - + .donutChart { width: 120px; height: 120px; } - + .memberCard { flex-direction: column; align-items: flex-start; gap: 10px; - } - + .buttonGroup { width: 100%; justify-content: space-between; } - + .validateButton, .rejectButton { flex: 1; text-align: center; padding: 8px; } -} - + .membersContainer { + max-height: 300px; + } +} \ No newline at end of file diff --git a/src/pages/Stat/test.jsx b/src/pages/Stat/test.jsx new file mode 100644 index 0000000..a1b4d7d --- /dev/null +++ b/src/pages/Stat/test.jsx @@ -0,0 +1,26 @@ +import React, { useState } from "react"; +import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; + +function TestDropdown() { + const [selected, setSelected] = useState("3"); + + return ( +
+ + Mois + + +
+ ); +} + +export default TestDropdown; \ No newline at end of file diff --git a/src/router.js b/src/router.js index f3fdef6..02af71a 100644 --- a/src/router.js +++ b/src/router.js @@ -8,6 +8,7 @@ import VolunteersPage from "./pages/Volunteers/VolunteersPage"; import ProfilePage from "./pages/Profile/ProfilePage"; import EventsPage from "./pages/Events/EventsPage.jsx"; + const router = createBrowserRouter([ { path: "/login", @@ -40,7 +41,11 @@ const router = createBrowserRouter([ { path: "/volunteers", Component: VolunteersPage, - } + }, + { + path: "/stat", + Component:StatPage, + }, ] } ]) From 944e1f0122d70865a252c1902aee18c783e559f9 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 13:58:50 +0100 Subject: [PATCH 07/48] Fix theme icon path --- src/components/ui/themeSwitcher/ThemeSwitcher.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ui/themeSwitcher/ThemeSwitcher.jsx b/src/components/ui/themeSwitcher/ThemeSwitcher.jsx index a3aa96f..ef3ffc6 100644 --- a/src/components/ui/themeSwitcher/ThemeSwitcher.jsx +++ b/src/components/ui/themeSwitcher/ThemeSwitcher.jsx @@ -26,7 +26,7 @@ export default function ThemeSwitcher() { }; return } \ No newline at end of file From 8aff1ff31c154f5ab0677f7cb63d913a3bb2144d Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 10 Dec 2025 14:00:17 +0100 Subject: [PATCH 08/48] resolve conflicts --- src/index.css | 4 +- src/pages/Stat/StatPage.jsx | 21 ++++------ src/pages/Stat/StatPage.module.css | 66 +++++++++++++++--------------- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/index.css b/src/index.css index ce69093..8b27bb9 100644 --- a/src/index.css +++ b/src/index.css @@ -48,7 +48,7 @@ body { } -.glassCard { +/*.glassCard { width: 100%; height: fit-content; background: rgba(255, 255, 255, 0.65); @@ -63,7 +63,7 @@ body { inset 0 0 8px 4px rgba(255, 255, 255, 0.4); position: relative; overflow: hidden; -} +}*/ .glassBorder{ border-radius: 20px; diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index 78a212b..9fe416d 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -32,9 +32,7 @@ function StatPage() { { title: "Événement D", tasks: "Communication sur les réseaux" }, { title: "Événement E", tasks: "Communication sur les réseaux" }, { title: "Événement F", tasks: "Communication sur les réseaux" }, - ]; - const pendingMembers = [ { name: "Antoine Ordonneau" }, { name: "Giovanni Josserand" }, @@ -48,11 +46,9 @@ function StatPage() { const handleValidate = (name) => { console.log(`Valider ${name}`); }; - const handleReject = (name) => { console.log(`Refuser ${name}`); }; - const chartData = { labels: ["Progress", "Background"], datasets: [ @@ -61,13 +57,12 @@ function StatPage() { backgroundColor: ["#1e60f9ff", "#ffffffff"], borderWidth: 0, weight: 10, - cutout: "95%", + cutout: "93%", circumference: 360, rotation: -90, }, ], }; - const chartOptions = { responsive: true, plugins: { @@ -83,23 +78,24 @@ function StatPage() { animateRotate: true, }, }; - return (
- - +
+ +
diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 68aa2ec..3491259 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -7,15 +7,7 @@ gap: 20px; } -/* style a montrer a giovanni prcq il est + bo */ -/*.glassCard { - background: rgba(255, 255, 255, 0.2); - backdrop-filter: blur(10px); - border-radius: 10px; - padding: 15px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - border: 1px solid rgba(255, 255, 255, 0.3); -}*/ + .block { border-radius: 10px; @@ -263,7 +255,6 @@ animation: slideInMember 0.5s ease forwards; } -/* Animation différée pour chaque carte de membre */ .memberCard:nth-child(1) { animation-delay: 0s; } @@ -304,49 +295,60 @@ @media screen and (max-width: 760px) { .container { flex-direction: column; - padding: 10px; + width:100%; + padding: 0 0 0 0; + /* padding: 10px;*/ } .leftBlock { width: 100%; - margin-bottom: 20px; + margin-top:20px; height: fit-content; } .rightSection { width: 100%; + margin:0 0 0 0; + margin-bottom: 15px; } - - + .rightBlock{ + width:100%; + margin-bottom: 0px; + } + + .rightBlock h2 { + font-size: 20px; +} .eventCard { width: 100%; + height:200px; + } + .eventCard h3{ + font-size:17px; } - .donutChart { width: 120px; height: 120px; } - - .memberCard { + .membersContainer { + max-height: 200px; + } + .partiText{ flex-direction: column; - align-items: flex-start; - gap: 10px; + justify-content: center; } - - .buttonGroup { - width: 100%; - justify-content: space-between; - } - - .validateButton, - .rejectButton { - flex: 1; + .partiText label{ text-align: center; - padding: 8px; + } + .formControl { + display: flex; + justify-content: center; + width: 100%; } - .membersContainer { - max-height: 300px; + .formDesign { + margin: 0 auto; + width: fit-content; } -} \ No newline at end of file + } \ No newline at end of file From bada53dc7f6f018a6605ef0b61361ab69bf706cb Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 10 Dec 2025 12:03:12 +0100 Subject: [PATCH 09/48] cut into components --- .env | 1 + .../IncompleteEvent/IncompleteEvent.jsx | 29 ++ .../IncompleteEvent.module.css | 76 ++++ .../PendingMembers/PendingMembers.jsx | 46 +++ .../PendingMembers/PendingMembers.module.css | 73 ++++ src/components/chart/ParticipationChart.jsx | 90 +++++ .../chart/ParticipationChart.module.css | 86 +++++ src/pages/Stat/StatPage.jsx | 180 +--------- src/pages/Stat/StatPage.module.css | 331 +----------------- 9 files changed, 416 insertions(+), 496 deletions(-) create mode 100644 .env create mode 100644 src/components/IncompleteEvent/IncompleteEvent.jsx create mode 100644 src/components/IncompleteEvent/IncompleteEvent.module.css create mode 100644 src/components/PendingMembers/PendingMembers.jsx create mode 100644 src/components/PendingMembers/PendingMembers.module.css create mode 100644 src/components/chart/ParticipationChart.jsx create mode 100644 src/components/chart/ParticipationChart.module.css diff --git a/.env b/.env new file mode 100644 index 0000000..50dcc6e --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_API_URL=localhost:80 \ No newline at end of file diff --git a/src/components/IncompleteEvent/IncompleteEvent.jsx b/src/components/IncompleteEvent/IncompleteEvent.jsx new file mode 100644 index 0000000..84dc2a9 --- /dev/null +++ b/src/components/IncompleteEvent/IncompleteEvent.jsx @@ -0,0 +1,29 @@ +import React from "react"; +import styles from "./IncompleteEvent.module.css"; + +function IncompleteEvent() { + const incompleteEvents = [ + { title: "Événement A", tasks: "Préparation des flyers" }, + { title: "Événement B", tasks: "Réservation de la salle" }, + { title: "Événement C", tasks: "Communication sur les réseaux" }, + { title: "Événement D", tasks: "Communication sur les réseaux" }, + { title: "Événement E", tasks: "Communication sur les réseaux" }, + { title: "Événement F", tasks: "Communication sur les réseaux" }, + ]; + + return ( +
+

Événements incomplets

+
+ {incompleteEvents.map((event, index) => ( +
+

{event.title}

+

{event.tasks}

+
+ ))} +
+
+ ); +} + +export default IncompleteEvent; diff --git a/src/components/IncompleteEvent/IncompleteEvent.module.css b/src/components/IncompleteEvent/IncompleteEvent.module.css new file mode 100644 index 0000000..e56e1f1 --- /dev/null +++ b/src/components/IncompleteEvent/IncompleteEvent.module.css @@ -0,0 +1,76 @@ +.rightBlock { + width: 100%; +} + +.rightBlock > h2 { + font-size: 29px; +} + +.eventsContainer { + display: flex; + flex-direction: row; + gap: 10px; + margin-top: 15px; + overflow-x: auto; + overflow-y: hidden; + padding-bottom: 10px; + scroll-behavior: smooth; +} + +.eventsContainer::-webkit-scrollbar { + height: 8px; +} + +.eventsContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb { + background: rgba(30, 96, 249, 0.5); + border-radius: 10px; +} + +.eventsContainer::-webkit-scrollbar-thumb:hover { + background: rgba(30, 96, 249, 0.7); +} + +.eventCard { + min-width: calc((100% - 20px) / 3); + max-width: calc((100% - 20px) / 3); + flex-shrink: 0; + padding: 10px; + text-align: center; + padding-bottom: 200px; + box-sizing: border-box; + opacity: 0; + transform: translateX(20px); + animation: slideInEvent 1s ease forwards; +} + +.eventCard:nth-child(1) { animation-delay: 0s; } +.eventCard:nth-child(2) { animation-delay: 0.1s; } +.eventCard:nth-child(3) { animation-delay: 0.2s; } +.eventCard:nth-child(4) { animation-delay: 0.3s; } +.eventCard:nth-child(5) { animation-delay: 0.4s; } +.eventCard:nth-child(6) { animation-delay: 0.5s; } + +.eventCard > h3 { + font-size: 24px; +} + +@keyframes slideInEvent { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); } +} + +@media screen and (max-width: 760px) { + .eventCard { + width: 100%; + height: 200px; + } + + .eventCard h3 { + font-size: 17px; + } +} diff --git a/src/components/PendingMembers/PendingMembers.jsx b/src/components/PendingMembers/PendingMembers.jsx new file mode 100644 index 0000000..27dace2 --- /dev/null +++ b/src/components/PendingMembers/PendingMembers.jsx @@ -0,0 +1,46 @@ +import React from "react"; +import Button from "../ui/button/button"; +import styles from "./PendingMembers.module.css"; + +function pendingMembers() { + const pendingMembers = [ + { name: "Antoine Ordonneau" }, + { name: "Giovanni Josserand" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" }, + { name: "Quentin T'Jampens" } + ]; + + const handleValidate = (name) => { + console.log(`Valider ${name}`); + }; + + const handleReject = (name) => { + console.log(`Refuser ${name}`); + }; + + return ( +
+

Membres en attente de validation

+
+ {pendingMembers.map((member, index) => ( +
+

{member.name}

+
+ + +
+
+ ))} +
+
+ ); +} + +export default pendingMembers; diff --git a/src/components/PendingMembers/PendingMembers.module.css b/src/components/PendingMembers/PendingMembers.module.css new file mode 100644 index 0000000..974b925 --- /dev/null +++ b/src/components/PendingMembers/PendingMembers.module.css @@ -0,0 +1,73 @@ +.rightBlock { + width: 100%; +} + +.rightBlock > h2 { + font-size: 29px; +} + +.membersContainer { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 15px; + max-height: 181px; + overflow-y: auto; + padding-right: 5px; + scroll-behavior: smooth; +} + +.membersContainer::-webkit-scrollbar { + width: 8px; +} + +.membersContainer::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 10px; +} + +.membersContainer::-webkit-scrollbar-thumb { + background: rgba(255, 0, 0, 0.5); + border-radius: 10px; +} + +.membersContainer::-webkit-scrollbar-thumb:hover { + background: rgba(125, 249, 30, 0.7); +} + +.memberCard { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + flex-shrink: 0; + opacity: 0; + transform: translateY(20px); + animation: slideInMember 0.5s ease forwards; +} + +.memberCard:nth-child(1) { animation-delay: 0s; } +.memberCard:nth-child(2) { animation-delay: 0.1s; } +.memberCard:nth-child(3) { animation-delay: 0.2s; } + +.memberCard p { + font-weight: bold; + font-size: 20px; +} + +.buttonGroup { + display: flex; + gap: 10px; + justify-content: right; +} + +@keyframes slideInMember { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +@media screen and (max-width: 760px) { + .membersContainer { + max-height: 200px; + } +} diff --git a/src/components/chart/ParticipationChart.jsx b/src/components/chart/ParticipationChart.jsx new file mode 100644 index 0000000..7648bf1 --- /dev/null +++ b/src/components/chart/ParticipationChart.jsx @@ -0,0 +1,90 @@ +import React, { useState } from "react"; +import { Doughnut } from "react-chartjs-2"; +import { Chart, ArcElement } from "chart.js"; +import { MenuItem, Select, FormControl } from "@mui/material"; +import styles from "./ParticipationChart.module.css"; + +Chart.register(ArcElement); + +function participationChart() { + const [selected, setSelected] = useState("3"); + const [participationRate, setParticipationRate] = useState(89); + + const chartData = { + labels: ["Progress", "Background"], + datasets: [ + { + data: [participationRate, 100 - participationRate], + backgroundColor: ["#1e60f9ff", "#ffffffff"], + borderWidth: 0, + weight: 10, + cutout: "93%", + circumference: 360, + rotation: -90, + }, + ], + }; + + const chartOptions = { + responsive: true, + plugins: { + legend: { display: false }, + tooltip: { enabled: false }, + }, + animation: { + animateScale: true, + animateRotate: true, + }, + }; + + return ( +
+
+
+ +
+ + + +
+
+
+
+
+ +
{participationRate}%
+
+
+
+ ); +} + +export default participationChart; diff --git a/src/components/chart/ParticipationChart.module.css b/src/components/chart/ParticipationChart.module.css new file mode 100644 index 0000000..9e16164 --- /dev/null +++ b/src/components/chart/ParticipationChart.module.css @@ -0,0 +1,86 @@ +.leftBlock { + width: 40%; + display: flex; + flex-direction: column; + align-items: center; + height: fit-content; +} + +.participationHeader { + display: flex; + align-items: center; + width: 100%; +} + +.partiText { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 2%; + margin-top: 2%; + animation: slideInEvent 2s; +} + +.partiText label { + font-size: 20px; + text-align: right; + transition: all 0.3s ease; +} + +.chartContainer { + max-width: 80%; + margin: 0 auto; + position: relative; + animation: slideEvent2 2s; +} + +.chartWrapper { + position: relative; + width: 100%; + height: 100%; + display: flex; + justify-content: center; +} + +.chartPercentage { + position: absolute; + top: 50%; + left: 50%; + text-align: center; + transform: translate(-50%, -50%); + font-size: 60px; + font-weight: bold; + color: #333; +} + +@keyframes slideEvent2 { + from { opacity: 0; transform: translateX(-20px); } + to { opacity: 1; transform: translateX(0); } +} + +@keyframes slideInEvent { + from { opacity: 0; transform: translateX(20px); } + to { opacity: 1; transform: translateX(0); } +} + +.formControl { + display: flex; + justify-content: center; + width: 100%; +} + +.formDesign { + margin: 0 auto; + width: fit-content; +} + +@media screen and (max-width: 760px) { + .partiText { + flex-direction: column; + justify-content: center; + } + + .partiText label { + text-align: center; + } +} diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Stat/StatPage.jsx index 9fe416d..fc2a4ef 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Stat/StatPage.jsx @@ -1,182 +1,26 @@ -import React, { useState, useEffect, useContext } from "react"; -import Dropdown from 'react-bootstrap/Dropdown'; -import { Doughnut } from "react-chartjs-2"; -import { Chart, ArcElement } from "chart.js"; +import React, { useState } from "react"; import styles from "./StatPage.module.css"; -import Button from "./../../components/ui/button/button"; -import { AuthContext } from "../../contexts/auth/AuthContext.js"; -import { useNavigate } from "react-router"; -import { readUsedSize } from "chart.js/helpers"; -import { MenuItem, Select, FormControl, InputLabel } from "@mui/material"; - -Chart.register(ArcElement); +// Importez les composants avec une majuscule +import ParticipationChart from "../../components/chart/ParticipationChart.jsx"; +import IncompleteEvents from "../../components/IncompleteEvent/IncompleteEvent.jsx"; +import PendingMembers from "../../components/PendingMembers/PendingMembers.jsx"; function StatPage() { - - const { user } = useContext(AuthContext); - const navigate = useNavigate(); - - const [months, setMonths] = useState(3); const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); - useEffect(() => { - if(!user.isAdmin) navigate("/") - }, []) - const incompleteEvents = [ - { title: "Événement A", tasks: "Préparation des flyers" }, - { title: "Événement B", tasks: "Réservation de la salle" }, - { title: "Événement C", tasks: "Communication sur les réseaux" }, - { title: "Événement D", tasks: "Communication sur les réseaux" }, - { title: "Événement E", tasks: "Communication sur les réseaux" }, - { title: "Événement F", tasks: "Communication sur les réseaux" }, - ]; - const pendingMembers = [ - { name: "Antoine Ordonneau" }, - { name: "Giovanni Josserand" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" }, - { name: "Quentin T'Jampens" } - ]; - - const handleValidate = (name) => { - console.log(`Valider ${name}`); - }; - const handleReject = (name) => { - console.log(`Refuser ${name}`); - }; - const chartData = { - labels: ["Progress", "Background"], - datasets: [ - { - data: [participationRate, 100 - participationRate], - backgroundColor: ["#1e60f9ff", "#ffffffff"], - borderWidth: 0, - weight: 10, - cutout: "93%", - circumference: 360, - rotation: -90, - }, - ], - }; - const chartOptions = { - responsive: true, - plugins: { - legend: { - display: false, - }, - tooltip: { - enabled: false, - }, - }, - animation: { - animateScale: true, - animateRotate: true, - }, - }; return (
-
-
-
- -
- - - -
- -
-
-
-
- -
- {participationRate}% -
-
-
-
+
-
-

Événements incomplets

-
- {incompleteEvents.map((event, index) => ( -
-

{event.title}

-

{event.tasks}

-
- ))} -
-
-
-

Membres en attente de validation

-
- {pendingMembers.map((member, index) => ( -
-

{member.name}

-
- - -
-
- ))} -
-
+ +
); diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Stat/StatPage.module.css index 3491259..ced6cdf 100644 --- a/src/pages/Stat/StatPage.module.css +++ b/src/pages/Stat/StatPage.module.css @@ -7,113 +7,6 @@ gap: 20px; } - - -.block { - border-radius: 10px; - padding: 15px; - box-sizing: border-box; -} - -.leftBlock { - width: 40%; - display: flex; - flex-direction: column; - align-items: center; - height: fit-content; -} - -.participationHeader { - display: flex; - align-items: center; - /*justify-content: center;*/ - text-align: center; - margin-bottom: 0px; - width: 100%; -} -.participationHeader #months{ - text-align:center; -} - -.partiText { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 2%; - margin-top: 2%; - animation: slideInEvent 2s; -} - -.partiText label { - transition: all 0.3s ease; -} - - -.participationHeader label { - font-size: 20px; - text-align: right; -} -.participationHeader p{ - width:fit-content; -} - - -.chartContainer { - max-width: 80%; - margin: 0 auto; - position: relative; - - animation: slideEvent2 2s; -} - -@keyframes slideEvent2 { - from { - opacity: 0; - transform: translateX(-20px); - } - to { - opacity: 1; - transform: translateX(0); - } -} -.chartWrapper { - position: relative; - width: 100%; - height: 100%; - display: flex; - justify-content: center; -} - -.chartPercentage { - position: absolute; - top: 50%; - left: 50%; - text-align: center; - transform: translate(-50%, -50%); - font-size: 60px; - font-weight: bold; - color: #333; -} - -.circularProgress { - width: 100%; - height: 100%; -} - -.progressBackground { - opacity: 0.3; -} - -.progressBar { - transition: stroke-dasharray 0.5s ease; - stroke-linecap: round; -} - -.progressText { - font-weight: bold; - font-family: Arial, sans-serif; -} - .rightSection { width: 60%; display: flex; @@ -121,234 +14,16 @@ gap: 20px; } -.rightBlock { - width: 100%; -} - -.rightBlock > h2 { - font-size: 29px; -} - -.eventsContainer { - display: flex; - flex-direction: row; - gap: 10px; - margin-top: 15px; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: 10px; - scroll-behavior: smooth; -} - -/* Style de la scrollbar horizontale */ -.eventsContainer::-webkit-scrollbar { - height: 8px; -} - -.eventsContainer::-webkit-scrollbar-track { - background: rgba(0, 0, 0, 0.1); - border-radius: 10px; -} - -.eventsContainer::-webkit-scrollbar-thumb { - background: rgba(30, 96, 249, 0.5); - border-radius: 10px; -} - -.eventsContainer::-webkit-scrollbar-thumb:hover { - background: rgba(30, 96, 249, 0.7); -} - -.eventCard { - min-width: calc((100% - 20px) / 3); - max-width: calc((100% - 20px) / 3); - flex-shrink: 0; - padding: 10px; - text-align: center; - padding-bottom: 200px; - box-sizing: border-box; - opacity: 0; - transform: translateX(20px); - animation: slideInEvent 1s ease forwards; -} - -/* animation card */ -.eventCard:nth-child(1) { - animation-delay: 0s; -} - -.eventCard:nth-child(2) { - animation-delay: 0.1s; -} - -.eventCard:nth-child(3) { - animation-delay: 0.2s; -} - -.eventCard:nth-child(4) { - animation-delay: 0.3s; -} - -.eventCard:nth-child(5) { - animation-delay: 0.4s; -} - -.eventCard:nth-child(6) { - animation-delay: 0.5s; -} - - -@keyframes slideInEvent { - from { - opacity: 0; - transform: translateX(20px); - } - to { - opacity: 1; - transform: translateX(0); - } -} - -.eventCard > h3 { - font-size: 24px; -} - -.membersContainer { - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 15px; - max-height: 181px; - overflow-y: auto; - padding-right: 5px; - scroll-behavior: smooth; -} - -/* style scrollbar */ -.membersContainer.membersContainer::-webkit-scrollbar { - width: 8px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-track { - background: rgba(0, 0, 0, 0.1); - border-radius: 10px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-thumb { - background: red; - border-radius: 10px; -} - -.membersContainer.membersContainer::-webkit-scrollbar-thumb:hover { - background: rgba(125, 249, 30, 0.7); -} - -/*//////*/ -.memberCard { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px; - flex-shrink: 0; - opacity: 0; - transform: translateY(20px); - animation: slideInMember 0.5s ease forwards; -} - -.memberCard:nth-child(1) { - animation-delay: 0s; -} - -.memberCard:nth-child(2) { - animation-delay: 0.1s; -} - -.memberCard:nth-child(3) { - animation-delay: 0.2s; -} - - - - -@keyframes slideInMember { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.memberCard p { - font-weight: bold; - font-size: 20px; -} - -.buttonGroup { - display: flex; - gap: 10px; - justify-content: right; -} - @media screen and (max-width: 760px) { .container { flex-direction: column; - width:100%; - padding: 0 0 0 0; - /* padding: 10px;*/ - } - - .leftBlock { width: 100%; - margin-top:20px; - height: fit-content; + padding: 0; } - + .rightSection { width: 100%; - margin:0 0 0 0; + margin: 0; margin-bottom: 15px; } - .rightBlock{ - width:100%; - margin-bottom: 0px; - } - - .rightBlock h2 { - font-size: 20px; } - - .eventCard { - width: 100%; - height:200px; - } - .eventCard h3{ - font-size:17px; - } - .donutChart { - width: 120px; - height: 120px; - } - .membersContainer { - max-height: 200px; - } - .partiText{ - flex-direction: column; - justify-content: center; - } - .partiText label{ - text-align: center; - } - .formControl { - display: flex; - justify-content: center; - width: 100%; - } - - .formDesign { - margin: 0 auto; - width: fit-content; - } - } \ No newline at end of file From 8f93d6369a69162a55c31b41eb687b70d995e155 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 14:01:43 +0100 Subject: [PATCH 10/48] remove console.log --- src/contexts/auth/authProvider.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/contexts/auth/authProvider.jsx b/src/contexts/auth/authProvider.jsx index 5fd87ca..850c3a2 100644 --- a/src/contexts/auth/authProvider.jsx +++ b/src/contexts/auth/authProvider.jsx @@ -14,7 +14,6 @@ export function AuthProvider({ children }) { const u = await getUser(); setUser(u); setLoading(false); - console.log(u); })(); }, []); From 13ef35cdb319d661a62ea5ce89d0d4da8513c8a3 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 14:07:51 +0100 Subject: [PATCH 11/48] change page title and icone --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 764759f..7ecd944 100644 --- a/index.html +++ b/index.html @@ -2,9 +2,9 @@ - + - sae-front + Comité des fêtes de Beaupont
From 019296a845f1aa93c431ba07de0ddd9920bafbf2 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 14:08:01 +0100 Subject: [PATCH 12/48] change page title and icone --- public/logoIcone.png | Bin 0 -> 51177 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/logoIcone.png diff --git a/public/logoIcone.png b/public/logoIcone.png new file mode 100644 index 0000000000000000000000000000000000000000..b8baa922d824feb1f5f84de7613e76667b46316b GIT binary patch literal 51177 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 Rfe8G8KGb|rqHOv6{{h{TH~atq literal 0 HcmV?d00001 From 45dda2ef0a9f7030d1e548e06c6b4f301be97d43 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 14:10:41 +0100 Subject: [PATCH 13/48] Fix path --- src/pages/Volunteers/VolunteerCard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Volunteers/VolunteerCard.jsx b/src/pages/Volunteers/VolunteerCard.jsx index fe1cf00..fb58440 100644 --- a/src/pages/Volunteers/VolunteerCard.jsx +++ b/src/pages/Volunteers/VolunteerCard.jsx @@ -58,7 +58,7 @@ export default function VolunteerCard({ user }) { {isExpanded && (
- - - + profile
diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 4aba8b2..1aaa72b 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -105,10 +105,6 @@ border-bottom: 2px solid #019AFF; } -svg { - width: fit-content; -} - .bellBtn, .profileLink { display: flex; align-items: center; @@ -124,11 +120,12 @@ svg { position: relative; } -.bellBtn svg { +.notificationsImg { stroke: black; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; + height: 28px; } .bellBtn:focus { @@ -141,33 +138,22 @@ svg { .activeBellBtn { transform: translateY(-4px); background: rgba(191, 191, 191, 0.5); - svg { - stroke: #019AFF; - } } + .bellBtn:hover { transform: translateY(-4px); background: rgba(191, 191, 191, 0.5); - svg { - stroke: #019AFF; - } } .profileLink:hover { transform: translateY(-4px); background: rgba(191, 191, 191, 0.5); - svg { - fill: #019AFF; - } } -.bellBtn svg { - height: 28px; -} -.profileLink svg { +.profileImg { height: 40px; } @@ -188,7 +174,6 @@ svg { z-index: 3; } - .notification{ margin-bottom: 7%; display: flex; @@ -233,6 +218,7 @@ svg { cursor: pointer; display: none; z-index: 10; + background: none; } .burgerBar { From 9767b4029fa330dac2f5eb19fb7311d714388416 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 14:57:43 +0100 Subject: [PATCH 17/48] Change login path --- src/contexts/auth/authProvider.jsx | 2 +- src/utils/{ => auth}/login.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/utils/{ => auth}/login.js (95%) diff --git a/src/contexts/auth/authProvider.jsx b/src/contexts/auth/authProvider.jsx index 850c3a2..7df3f1d 100644 --- a/src/contexts/auth/authProvider.jsx +++ b/src/contexts/auth/authProvider.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import loginFunction from "../../utils/login.js"; +import loginFunction from "../../utils/auth/login.js"; import getUser from "../../utils/getUser.js"; import { AuthContext } from "./AuthContext"; import logoutFunction from "../../utils/auth/logout.js" diff --git a/src/utils/login.js b/src/utils/auth/login.js similarity index 95% rename from src/utils/login.js rename to src/utils/auth/login.js index 161268c..a9d972b 100644 --- a/src/utils/login.js +++ b/src/utils/auth/login.js @@ -1,4 +1,4 @@ -import getXSRFToken from "./getXSRF.js"; +import getXSRFToken from "../getXSRF.js"; export default async function login(email, password) { const csrfToken = await getXSRFToken(); From 562a570ddaa22c41fdbd915d8e8dfac58d739c29 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 14:57:50 +0100 Subject: [PATCH 18/48] Add unit test --- src/utils/auth/login.test.js | 56 +++++++++++++++++++++++++++++++++++ src/utils/auth/logout.test.js | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/utils/auth/login.test.js create mode 100644 src/utils/auth/logout.test.js diff --git a/src/utils/auth/login.test.js b/src/utils/auth/login.test.js new file mode 100644 index 0000000..b37f9f9 --- /dev/null +++ b/src/utils/auth/login.test.js @@ -0,0 +1,56 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import login from './login'; + +vi.mock('../getXSRF.js', () => ({ + default: vi.fn(() => Promise.resolve('fake-csrf-token')) +})); + +describe('login()', () => { + + beforeEach(() => { + vi.clearAllMocks(); + global.fetch = vi.fn(); + }); + + it('envoie la requête de login et retourne les données utilisateur', async () => { + global.fetch.mockResolvedValue({ + ok: true, + status: 200, + json: async () => ({ id: 1, name: 'John Doe' }) + }); + + const result = await login('test@example.com', 'secret'); + + expect(global.fetch).toHaveBeenCalledOnce(); + expect(global.fetch).toHaveBeenCalledWith( + `http://${import.meta.env.VITE_API_URL}/api/users/login`, + { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'X-XSRF-TOKEN': 'fake-csrf-token', + 'Accept': 'application/json' + }, + body: JSON.stringify({ email: 'test@example.com', password: 'secret' }) + } + ); + + expect(result).toEqual({ + status: 200, + data: { id: 1, name: 'John Doe' } + }); + }); + + it('retourne une erreur quand la réponse HTTP est mauvaise', async () => { + global.fetch.mockResolvedValue({ + ok: false, + status: 401 + }); + + const result = await login('x', 'y'); + + expect(result).toBeInstanceOf(Error); + expect(result.message).toBe('Erreur HTTP 401'); + }); +}); diff --git a/src/utils/auth/logout.test.js b/src/utils/auth/logout.test.js new file mode 100644 index 0000000..f553e2e --- /dev/null +++ b/src/utils/auth/logout.test.js @@ -0,0 +1,53 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import logout from './logout'; + +vi.mock('../getXSRF.js', () => { + return { + default: vi.fn(() => Promise.resolve('fake-csrf-token')) + }; +}); + +describe('logout()', () => { + + beforeEach(() => { + vi.clearAllMocks(); + global.fetch = vi.fn(); + }); + + it('envoie bien la requête de logout', async () => { + global.fetch.mockResolvedValue({ + ok: true, + status: 200 + }); + + const result = await logout(); + + expect(global.fetch).toHaveBeenCalledOnce(); + expect(global.fetch).toHaveBeenCalledWith( + `http://${import.meta.env.VITE_API_URL}/api/users/logout`, + { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-XSRF-TOKEN': 'fake-csrf-token' + }, + } + ); + + expect(result).toEqual({ status: 200 }); + }); + + it('renvoie une erreur quand la réponse HTTP est mauvaise', async () => { + global.fetch.mockResolvedValue({ + ok: false, + status: 500 + }); + + const result = await logout(); + + expect(result).toBeInstanceOf(Error); + expect(result.message).toBe('Erreur HTTP 500'); + }); +}); From 1e4cb508ccee1d94318b7a5900ecf5aa12341b21 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:07:29 +0100 Subject: [PATCH 19/48] change header svg by img tag --- src/components/Header/Header.jsx | 11 ++++++----- src/components/Header/Header.module.css | 3 ++- src/components/SearchBar/SearchBar.module.css | 1 - 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 1a44fdb..4ee13ff 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -7,7 +7,7 @@ function Header() { const [notificationMenu, setnotificationMenu] = useState(false); const [unreadNotification, setunreadNotification] = useState(true); const [mobileMenu, setMobileMenu] = useState(false); - const [notifications, setNotifications] = useState([]); + const [notifications, setNotifications] = useState([{"content" : "ok"}, {"content" : "pourquoi pas antoine"}]); const notificationRef = useRef(null); @@ -15,7 +15,10 @@ function Header() { useEffect(() => { async function loadNotifications() { const notifData = await getUserNotifications(); + /* setNotifications(notifData || []); + */ + } //loadNotifications(); @@ -105,7 +108,7 @@ function Header() { className={`${styles.notificationDiv} glassCard ${notificationMenu ? styles.activeNotificationDiv : ""}`} > {notifications.length === 0 ? ( -

Vous n'avez aucune notification !

+

Vous n'avez aucune notification !

) : ( notifications.map((notification, index) => (
@@ -114,9 +117,7 @@ function Header() { className={styles.closeBtn} onClick={() => setNotifications(prev => prev.filter((_, i) => i !== index))} > - - - + supprimer la notification
)) diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 1aaa72b..c9ffc2b 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -175,10 +175,11 @@ } .notification{ - margin-bottom: 7%; + padding: 0.5em 1em; display: flex; justify-content: space-between; align-items: center; + border-radius: 15px; } .notificationBadge { diff --git a/src/components/SearchBar/SearchBar.module.css b/src/components/SearchBar/SearchBar.module.css index a58f1de..d35c808 100644 --- a/src/components/SearchBar/SearchBar.module.css +++ b/src/components/SearchBar/SearchBar.module.css @@ -31,7 +31,6 @@ .searchedEvent{ display: flex; padding: 0.5rem; - border-radius: 15px; align-items: center; } From 4fce23843ec4758b6c46f456a445c3f8b40e608c Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:27:26 +0100 Subject: [PATCH 20/48] change filter svg by img tag --- public/sortByAntiAlpha.svg | 2 +- src/components/Filter/Filter.jsx | 18 ++++-------------- src/components/Filter/Filter.module.css | 19 +------------------ src/components/ToolBar/ToolBar.module.css | 5 ++++- 4 files changed, 10 insertions(+), 34 deletions(-) diff --git a/public/sortByAntiAlpha.svg b/public/sortByAntiAlpha.svg index f74e5d8..adea5c6 100644 --- a/public/sortByAntiAlpha.svg +++ b/public/sortByAntiAlpha.svg @@ -1,4 +1,4 @@ - + diff --git a/src/components/Filter/Filter.jsx b/src/components/Filter/Filter.jsx index 6e70259..3dcf4ae 100644 --- a/src/components/Filter/Filter.jsx +++ b/src/components/Filter/Filter.jsx @@ -20,38 +20,28 @@ function Filter({isFilterVisible, filters, setFilters}){ Tri alphabétique croissant (A à Z)
diff --git a/src/components/Filter/Filter.module.css b/src/components/Filter/Filter.module.css index 38902fc..030dbe5 100644 --- a/src/components/Filter/Filter.module.css +++ b/src/components/Filter/Filter.module.css @@ -35,31 +35,14 @@ .filterTag:focus { outline: none; } -.filterTag:focus-visible { - outline: 2px solid black; -} .filterTag:hover { cursor: pointer; - svg{ - fill: #019AFF; - } -} - - -.filterTag svg { - transform: scale(0.7); - color: black; } .active { - border: 1px solid #019AFF; -} - -.active svg { - fill: #019AFF; - transform: scale(0.8); + border: 2px solid #019AFF; } @media screen and (max-width: 768px){ diff --git a/src/components/ToolBar/ToolBar.module.css b/src/components/ToolBar/ToolBar.module.css index 1b53950..bb04573 100644 --- a/src/components/ToolBar/ToolBar.module.css +++ b/src/components/ToolBar/ToolBar.module.css @@ -16,6 +16,9 @@ padding: 0; border-radius: 30px; overflow: visible; + display: flex; + align-items: center; + flex-direction: column; } .filterMenu{ @@ -93,8 +96,8 @@ } .filterContainer{ - display: flex; width: fit-content; + flex-direction: row; } .filterMenu{ From 76f7d16733c6bf8447748ed6a553fd74980c88c3 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:27:43 +0100 Subject: [PATCH 21/48] change filter svg by img tag --- src/components/Header/Header.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 4ee13ff..03a1161 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -15,10 +15,7 @@ function Header() { useEffect(() => { async function loadNotifications() { const notifData = await getUserNotifications(); - /* setNotifications(notifData || []); - */ - } //loadNotifications(); From 7fff6177b47d836c6d38dc5b863b929c6b13df04 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:34:41 +0100 Subject: [PATCH 22/48] change tool bar svg by img tag --- public/filter.svg | 1 + src/components/ToolBar/ToolBar.jsx | 8 ++------ src/components/ToolBar/ToolBar.module.css | 7 +------ 3 files changed, 4 insertions(+), 12 deletions(-) create mode 100644 public/filter.svg diff --git a/public/filter.svg b/public/filter.svg new file mode 100644 index 0000000..6096a31 --- /dev/null +++ b/public/filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/ToolBar/ToolBar.jsx b/src/components/ToolBar/ToolBar.jsx index 7788f59..56f0bca 100644 --- a/src/components/ToolBar/ToolBar.jsx +++ b/src/components/ToolBar/ToolBar.jsx @@ -43,16 +43,12 @@ function ToolBar({setFilters, filters}) {
diff --git a/src/components/ToolBar/ToolBar.module.css b/src/components/ToolBar/ToolBar.module.css index bb04573..1d86e23 100644 --- a/src/components/ToolBar/ToolBar.module.css +++ b/src/components/ToolBar/ToolBar.module.css @@ -39,7 +39,7 @@ .createButton { font-size: 2rem; - color: #019AFF; + color: black; } .createButton:hover, .searchButton:hover, .mobileFilter:hover { @@ -63,11 +63,6 @@ justify-content: center; } -.sortButton svg, .searchButton svg { - transform: scale(0.5); - fill: #019AFF; -} - .sortButton:focus, .searchButton:focus { outline: none; From 95a167c66362478e03f595c29fd7a55ebe8e5a99 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 10 Dec 2025 15:35:12 +0100 Subject: [PATCH 23/48] Handle login errors --- src/components/loginform/loginForm.jsx | 21 +++++++++++++++------ src/contexts/auth/authProvider.jsx | 6 +++--- src/utils/auth/login.js | 13 +++++++------ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/components/loginform/loginForm.jsx b/src/components/loginform/loginForm.jsx index 7562cba..74eb1ee 100644 --- a/src/components/loginform/loginForm.jsx +++ b/src/components/loginform/loginForm.jsx @@ -2,20 +2,25 @@ import { useState, useContext } from "react"; import styles from "./loginForm.module.css"; import Button from "../ui/button/button.jsx"; import Input from "../ui/input/input.jsx"; +import Modal from "../ui/modal/modal.jsx"; import { useNavigate } from "react-router"; import { AuthContext } from "../../contexts/auth/AuthContext.js"; function LoginForm({ className }) { + + + const navigate = useNavigate(); + const { login } = useContext(AuthContext); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); - let navigate = useNavigate(); - const { login } = useContext(AuthContext); + const [open , setOpen] = useState(false); + + async function handleSubmit() { + const res = await login(email, password); + if (res.status === 401 || res.status === 422) setOpen(true); + else navigate("/"); - async function handleSubmit(e) { - e.preventDefault(); - await login(email, password); - navigate("/"); } return ( @@ -37,6 +42,10 @@ function LoginForm({ className }) {
+ + setOpen(false)}> +

L'Email ou le mot de passe est incorrect

+
); } diff --git a/src/contexts/auth/authProvider.jsx b/src/contexts/auth/authProvider.jsx index 7df3f1d..666338f 100644 --- a/src/contexts/auth/authProvider.jsx +++ b/src/contexts/auth/authProvider.jsx @@ -19,12 +19,12 @@ export function AuthProvider({ children }) { const login = async (email, password) => { const res = await loginFunction(email, password); - if (!res || res.status !== 200) throw new Error("Login error"); - const u = await getUser(); - setUser(u); + const u = res.status === 200 ? await getUser() : null; + if (u) setUser(u); return res; }; + const logout = async () => { await logoutFunction(); setUser(null); diff --git a/src/utils/auth/login.js b/src/utils/auth/login.js index a9d972b..c925521 100644 --- a/src/utils/auth/login.js +++ b/src/utils/auth/login.js @@ -15,17 +15,18 @@ export default async function login(email, password) { body: JSON.stringify({ email, password }) }); - console.log('Code HTTP :', response.status); + const data = await response.json(); if (!response.ok) { - throw new Error(`Erreur HTTP ${response.status}`); + return { + status: response.status, + errors: data.errors || data.message + }; } - const data = await response.json(); - console.log('Connexion réussie ! Données utilisateur :', data); - return { status: response.status, data }; + } catch (error) { - return error; + return { status: 500, error }; } } From 08506e01ecaa9ff66b4db979f61b243afe2a62d8 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:36:43 +0100 Subject: [PATCH 24/48] change search bar svg by img tag --- src/components/SearchBar/SearchBar.jsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/SearchBar/SearchBar.jsx b/src/components/SearchBar/SearchBar.jsx index ddd0521..d39f095 100644 --- a/src/components/SearchBar/SearchBar.jsx +++ b/src/components/SearchBar/SearchBar.jsx @@ -47,10 +47,7 @@ function SearchBar() { return (
element.preventDefault()}> - - - + Rechercher Date: Wed, 10 Dec 2025 15:41:12 +0100 Subject: [PATCH 25/48] Update login test --- src/utils/auth/login.test.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/utils/auth/login.test.js b/src/utils/auth/login.test.js index b37f9f9..aa20121 100644 --- a/src/utils/auth/login.test.js +++ b/src/utils/auth/login.test.js @@ -42,15 +42,28 @@ describe('login()', () => { }); }); - it('retourne une erreur quand la réponse HTTP est mauvaise', async () => { + it('retourne un objet avec status et erreurs quand la réponse HTTP est mauvaise', async () => { global.fetch.mockResolvedValue({ ok: false, - status: 401 + status: 401, + json: async () => ({ message: 'Unauthorized' }) }); const result = await login('x', 'y'); - expect(result).toBeInstanceOf(Error); - expect(result.message).toBe('Erreur HTTP 401'); + expect(result).toEqual({ + status: 401, + errors: 'Unauthorized' + }); + }); + + it('retourne un objet avec status 500 en cas d’exception', async () => { + global.fetch.mockImplementation(() => { throw new Error('Network Error') }); + + const result = await login('x', 'y'); + + expect(result.status).toBe(500); + expect(result.error).toBeInstanceOf(Error); + expect(result.error.message).toBe('Network Error'); }); }); From 2b1d4aa8ba1c91fd81eb1ab17d3193efc7e92331 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 15:45:01 +0100 Subject: [PATCH 26/48] remove useless animation --- src/components/Header/Header.module.css | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index c9ffc2b..87867ea 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -26,25 +26,16 @@ pointer-events: auto; } .inactiveHeaderContent{ - opacity: 0; - pointer-events: none; - transition: opacity 0.3s ease; - position: absolute; - top: 0.8rem; - left: 0.8rem; + display: none; } .inactiveMobileMenu{ - max-height: 0; - position: absolute; - top: 100%; - left: 0; + display: none; } .activeMobileMenu{ - transition: max-height 3s ease; - max-height: 500px; + height: fit-content; display: flex; flex-direction: column; align-items: start; From b6ba3f0f13076a7456d59cacf3e8d59202a306cd Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 16:03:41 +0100 Subject: [PATCH 27/48] set content with minimum height --- src/index.css | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/index.css b/src/index.css index ce69093..70a7c48 100644 --- a/src/index.css +++ b/src/index.css @@ -27,9 +27,13 @@ html { .content { - padding: 1.5rem; - z-index: 1; - width: 100%; + padding: 1.5rem; + z-index: 1; + width: 100%; + min-height: 100vh; + display: flex; + flex-direction: column; + justify-content: space-between; } a { From 6131914b51d6acdcfa0fe25252879d682f3bd105 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 16:41:46 +0100 Subject: [PATCH 28/48] change z-index --- src/components/ToolBar/ToolBar.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ToolBar/ToolBar.module.css b/src/components/ToolBar/ToolBar.module.css index 1d86e23..4244069 100644 --- a/src/components/ToolBar/ToolBar.module.css +++ b/src/components/ToolBar/ToolBar.module.css @@ -9,6 +9,7 @@ width: fit-content; height: fit-content; gap: 1rem; + z-index: 4; } From 76284a30f51d54cf5abe2d3e6c95a492130ec9ca Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Wed, 10 Dec 2025 16:46:31 +0100 Subject: [PATCH 29/48] remove create button when volunteers page --- src/components/Header/Header.module.css | 2 +- src/components/ToolBar/ToolBar.jsx | 14 ++++++++------ src/pages/Volunteers/VolunteersPage.jsx | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/Header/Header.module.css b/src/components/Header/Header.module.css index 87867ea..eac6e90 100644 --- a/src/components/Header/Header.module.css +++ b/src/components/Header/Header.module.css @@ -162,7 +162,7 @@ .activeNotificationDiv { opacity: 1; transform: translateY(0); - z-index: 3; + z-index: 5; } .notification{ diff --git a/src/components/ToolBar/ToolBar.jsx b/src/components/ToolBar/ToolBar.jsx index 56f0bca..d1f069f 100644 --- a/src/components/ToolBar/ToolBar.jsx +++ b/src/components/ToolBar/ToolBar.jsx @@ -5,7 +5,7 @@ import {useEffect, useState} from "react"; import SearchBar from "../SearchBar/SearchBar.jsx"; -function ToolBar({setFilters, filters}) { +function ToolBar({setFilters, filters, showCreate = true}) { const [isFilterVisible, setIsFilterVisible] = useState(false); const [isSearchVisible, setIsSearchVisible] = useState(false); const toggleFilters = () => { @@ -36,11 +36,13 @@ function ToolBar({setFilters, filters}) {
) : null}
- - + - + {showCreate ? ( + + + + + ) : null} + + setIsOpen(false)}> + + + + + +} \ No newline at end of file diff --git a/src/components/createEventBtn/createEventBtn.module.css b/src/components/createEventBtn/createEventBtn.module.css new file mode 100644 index 0000000..fae169d --- /dev/null +++ b/src/components/createEventBtn/createEventBtn.module.css @@ -0,0 +1,20 @@ +.createButton { + font-size: 1.5rem; + color: black; +} + +.createButton { + display: flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 50% !important; + width: 55px !important; + height: 55px !important; + transition: all 0.5s ease; +} + +.createButton:hover { + transform: translateY(-5px); + cursor: pointer; +} \ No newline at end of file From 67b02c297f65916dc7ceb8587cb16cbdb52de5fa Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 15 Dec 2025 15:31:56 +0100 Subject: [PATCH 32/48] Create event function --- src/utils/event/createEvent.js | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/utils/event/createEvent.js diff --git a/src/utils/event/createEvent.js b/src/utils/event/createEvent.js new file mode 100644 index 0000000..4098dd7 --- /dev/null +++ b/src/utils/event/createEvent.js @@ -0,0 +1,36 @@ +import getXSRFToken from "../getXSRF.js"; + +export default async function createEvent(name, description) { + const csrfToken = await getXSRFToken(); + + try { + const response = await fetch(`http://${import.meta.env.VITE_API_URL}/api/events/create`, { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + 'X-XSRF-TOKEN': csrfToken, + 'Accept': 'application/json' + }, + body: JSON.stringify({ name, description }), + }); + + const data = await response.json(); + + if (!response.ok) { + if (response.status === 422) { + return { + status: 422, + errors: data.errors + }; + } + + throw new Error(`Erreur HTTP ${response.status}`); + } + + return { status: response.status, data }; + + } catch (error) { + return { status: "error", error }; + } +} From 9ad78b342e6735bec7bdd04e95b7f81fcc262a2e Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 15 Dec 2025 15:32:11 +0100 Subject: [PATCH 33/48] Call create function + update style --- .../createEventBtn/CreateEventBtn.jsx | 22 +++++++++++++++++++ .../createEventBtn/createEventBtn.module.css | 21 ++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/components/createEventBtn/CreateEventBtn.jsx b/src/components/createEventBtn/CreateEventBtn.jsx index 9a4a7c2..3e638db 100644 --- a/src/components/createEventBtn/CreateEventBtn.jsx +++ b/src/components/createEventBtn/CreateEventBtn.jsx @@ -2,19 +2,41 @@ import styles from "./createEventBtn.module.css" import { useState } from "react"; import Modal from "../ui/modal/modal.jsx"; import Button from "../ui/button/button.jsx"; +import TextInput from "../ui/input/input.jsx"; +import createEvent from "../../utils/event/createEvent.js" export default function CreateEventBtn() { const [isOpen, setIsOpen] = useState(false); + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + + const handleCreateEvent = async () => { + + if(name !== "" || description !== "") await createEvent(name, description); + setIsOpen(false); + } return <> setIsOpen(false)}> +
+
+

Titre

+ setName(e.target.value)} /> +
+
+

Description

+ setDescription(e.target.value)} /> +
+ + +
} \ No newline at end of file diff --git a/src/components/createEventBtn/createEventBtn.module.css b/src/components/createEventBtn/createEventBtn.module.css index fae169d..5676052 100644 --- a/src/components/createEventBtn/createEventBtn.module.css +++ b/src/components/createEventBtn/createEventBtn.module.css @@ -17,4 +17,25 @@ .createButton:hover { transform: translateY(-5px); cursor: pointer; +} + +.inputContainer { + + h2 { + margin-bottom: 0.5rem; + } + + margin: 1em; +} + +.create { + align-self: center; +} + +.section { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 15px; + margin-bottom: 15px; } \ No newline at end of file From 3051a0b2ca49bb09f7f191555ebebd5f210b447e Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 15 Dec 2025 16:49:07 +0100 Subject: [PATCH 34/48] Create ValidationErrorPage --- src/layout.jsx | 1 + .../ValidationErrorPage.jsx | 30 +++++++++++++++++++ .../validationErrorPage.module.css | 25 ++++++++++++++++ src/router.js | 5 ++++ 4 files changed, 61 insertions(+) create mode 100644 src/pages/waitValidationPage/ValidationErrorPage.jsx create mode 100644 src/pages/waitValidationPage/validationErrorPage.module.css diff --git a/src/layout.jsx b/src/layout.jsx index 4689a4e..4fa0991 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -13,6 +13,7 @@ function Layout(){ if (loading) return

Loading

; if (!user) return ; + if(user && user.validate === 0) return ; return (
diff --git a/src/pages/waitValidationPage/ValidationErrorPage.jsx b/src/pages/waitValidationPage/ValidationErrorPage.jsx new file mode 100644 index 0000000..15995e9 --- /dev/null +++ b/src/pages/waitValidationPage/ValidationErrorPage.jsx @@ -0,0 +1,30 @@ +import styles from "./validationErrorPage.module.css" +import Background from "../../components/background/background.jsx"; +import Button from "../../components/ui/button/button.jsx"; +import { useContext } from "react"; +import { AuthContext } from "../../contexts/auth/AuthContext.js"; +import { Navigate, useNavigate } from "react-router"; + +export default function ValidationErrorPage() { + + const { logout, user } = useContext(AuthContext); + const navigate = useNavigate(); + + const handleLogout = async () => { + await logout(); + navigate("/login"); + } + + if(user && user.validate === 1) return ; + + return +
+

Votre compte n'a pas été validé

+
+

Votre compte n'a pas encore été validé, veuillez attendre la vérification de votre compte par un membre autorisé.

+

Contact : contact@example.com

+ +
+
+
+} \ No newline at end of file diff --git a/src/pages/waitValidationPage/validationErrorPage.module.css b/src/pages/waitValidationPage/validationErrorPage.module.css new file mode 100644 index 0000000..e4a398d --- /dev/null +++ b/src/pages/waitValidationPage/validationErrorPage.module.css @@ -0,0 +1,25 @@ +.title { + color: white; + font-size: xx-large; + margin-bottom: 20px; +} + +.content { + display: flex; + flex-direction: column; + z-index: 2; + padding: 10px; +} + +.container { + padding: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 15px; + + p { + font-size: large; + } +} \ No newline at end of file diff --git a/src/router.js b/src/router.js index f3fdef6..bf44302 100644 --- a/src/router.js +++ b/src/router.js @@ -7,6 +7,7 @@ import RegisterPage from "./pages/Register/RegisterPage.jsx"; import VolunteersPage from "./pages/Volunteers/VolunteersPage"; import ProfilePage from "./pages/Profile/ProfilePage"; import EventsPage from "./pages/Events/EventsPage.jsx"; +import ValidationErrorPage from "./pages/waitValidationPage/ValidationErrorPage.jsx"; const router = createBrowserRouter([ { @@ -17,6 +18,10 @@ const router = createBrowserRouter([ path: "/register", Component: RegisterPage, }, + { + path: "/error/validation", + Component: ValidationErrorPage + }, { path: "/", Component: Layout, From 7fa9b74bd8ed329c5a18daa8f8954f60066463c9 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 15 Dec 2025 17:04:06 +0100 Subject: [PATCH 35/48] Create ThemeSwitcher story --- src/stories/ThemeSwitcher.stories.jsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/stories/ThemeSwitcher.stories.jsx diff --git a/src/stories/ThemeSwitcher.stories.jsx b/src/stories/ThemeSwitcher.stories.jsx new file mode 100644 index 0000000..f285b15 --- /dev/null +++ b/src/stories/ThemeSwitcher.stories.jsx @@ -0,0 +1,20 @@ +import ThemeSwitcher from "../components/ui/themeSwitcher/ThemeSwitcher.jsx"; +import Background from "../components/background/background.jsx"; + +export default { + title: 'UI/ThemeSwitcher', + component: ThemeSwitcher, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +}; + +const ThemeSwitcherRender = () => { + return + + +}; + +export const Default = () => ; + From 9f681d6345eabaf3a1df255e5bcb0f5d7a4c414a Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 14:32:04 +0100 Subject: [PATCH 36/48] Create VolunteerProfilePage --- src/pages/VolunteerProfile/VolunteerProfilePage.jsx | 13 +++++++++++++ .../VolunteerProfilePage.module.css | 0 src/router.js | 5 +++++ 3 files changed, 18 insertions(+) create mode 100644 src/pages/VolunteerProfile/VolunteerProfilePage.jsx create mode 100644 src/pages/VolunteerProfile/VolunteerProfilePage.module.css diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx new file mode 100644 index 0000000..f56ec75 --- /dev/null +++ b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx @@ -0,0 +1,13 @@ +import styles from "./VolunteerProfilePage.module.css" +import { useParams } from "react-router"; + + +export default function VolunteerProfilePage() { + + const params = useParams(); + const id = params.id; + + return
+ +
+} \ No newline at end of file diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.module.css b/src/pages/VolunteerProfile/VolunteerProfilePage.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/router.js b/src/router.js index bf44302..25c91b9 100644 --- a/src/router.js +++ b/src/router.js @@ -8,6 +8,7 @@ import VolunteersPage from "./pages/Volunteers/VolunteersPage"; import ProfilePage from "./pages/Profile/ProfilePage"; import EventsPage from "./pages/Events/EventsPage.jsx"; import ValidationErrorPage from "./pages/waitValidationPage/ValidationErrorPage.jsx"; +import VolunteerProfilePage from "./pages/VolunteerProfile/VolunteerProfilePage.jsx"; const router = createBrowserRouter([ { @@ -45,6 +46,10 @@ const router = createBrowserRouter([ { path: "/volunteers", Component: VolunteersPage, + }, + { + path: "/profile/:id", + Component: VolunteerProfilePage, } ] } From 204caf3a8c3e19a6d78ad3e79fdb2c8be6851ad0 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 14:34:56 +0100 Subject: [PATCH 37/48] Fix logo --- src/components/Header/Header.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 03a1161..ee04918 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -41,7 +41,7 @@ function Header() { @@ -114,7 +114,7 @@ function Header() { className={styles.closeBtn} onClick={() => setNotifications(prev => prev.filter((_, i) => i !== index))} > - supprimer la notification + supprimer la notification
)) From 20bbc62b3d01797ebd04c73b71f4895dbc8311d1 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 14:46:19 +0100 Subject: [PATCH 39/48] Link VolunteerProfilePage to backend server --- .../VolunteerProfile/VolunteerProfilePage.jsx | 52 +++++- .../VolunteerProfilePage.module.css | 164 ++++++++++++++++++ 2 files changed, 214 insertions(+), 2 deletions(-) diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx index f56ec75..06b4ee3 100644 --- a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx +++ b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx @@ -1,13 +1,61 @@ import styles from "./VolunteerProfilePage.module.css" import { useParams } from "react-router"; - +import { useEffect, useState } from "react"; +import getUserById from "../../utils/users/getUserById.js"; +import formatDate from "../../utils/date/formatDate.js"; +import Task from "../../components/Task/Task.jsx"; export default function VolunteerProfilePage() { const params = useParams(); const id = params.id; - return
+ const [user, setUser] = useState({}); + useEffect(() => { + (async () => { + const data = await getUserById(id); + setUser(data); + }) () + }, []); + + + return
+
+
+
+ Photo de profil +
+
+
+

{user.name} {user.lastname}

+
+
+
+

Role : {user.role}

+

Membre depuis : {formatDate(user.created_at)}

+
+
+

Mail : {user.email}

+

Téléphone : {user.phone === null ? "Pas de numéro enregistré" : user.phone}

+
+
+ +

Tâches :

+ {user.tasks && user.tasks.length > 0 ? ( + user.tasks.map((task, index) => ( + + )) + ) : ( +

Aucune tâche pour le moment.

+ )} + +
+
+
} \ No newline at end of file diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.module.css b/src/pages/VolunteerProfile/VolunteerProfilePage.module.css index e69de29..e9861dc 100644 --- a/src/pages/VolunteerProfile/VolunteerProfilePage.module.css +++ b/src/pages/VolunteerProfile/VolunteerProfilePage.module.css @@ -0,0 +1,164 @@ +.container { + width: 100%; + padding: 10px; + box-sizing: border-box; +} + +.profileboard { + width: 100%; + padding: 15px; + border-radius: 20px; + box-sizing: border-box; +} + +.contentWrapper { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; +} + +.profilePictureContainer { + width: 120px; + height: 120px; + margin-bottom: 15px; +} + +.profilePicture { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; +} + +.description { + width: 100%; + text-align: left; + margin-left:4%; +} + +.topDescription { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + margin-bottom: 15px; +} + +.infoBlock { + width: 100%; + background: rgba(255, 255, 255, 0.1); + padding: 10px; + border-radius: 5px; +} + +.eventTasks { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out, opacity 0.2s ease; + opacity: 0; + padding-left: 20px; +} + +.eventTasks.expanded { + max-height: 500px; + opacity: 1; + margin-top: 10px; +} +.description h2{ + font-size:30px; + +} +.profilePicture{ + width:90%; +} + +.settingsBtns { + display: flex; + gap: 5px; + justify-content: right; +} + +@media screen and (min-width: 768px) { + .contentWrapper { + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; + } + + .profilePictureContainer { + width: 150px; + height: 150px; + margin-right: 20px; + margin-bottom: 0; + } + + .description { + width: calc(100% - 170px); + margin-left:4%; + } + + .topDescription { + flex-direction: row; + justify-content: space-between; + } + + .infoBlock { + width: 48%; + } + + .event { + padding: 15px; + } + .description h2{ + font-size:30px; + } + .profilePicture{ + width:90%; + } +} +.description button{ + width:50px; + height:50px; + +} + +.headerProfile { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +/* Desktop (1024px et plus) */ +@media screen and (min-width: 1024px) { + .container { + max-width: 100%; + margin: 0 auto; + padding: 20px; + } + + .profileboard { + padding: 25px; + } + + .profilePictureContainer { + width: 30%; + height:auto; + } + .profilePicture{ + width:90%; + } + .description { + width: calc(100% - 200px); + margin-left:4%; + } + + .event { + padding: 18px; + } + .description h2{ + font-size:30px; + } +} From 6147b98c523349c2cd84b46f73d68a2c614381c1 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 14:50:11 +0100 Subject: [PATCH 40/48] improve ux --- src/pages/Profile/ProfilePage.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile/ProfilePage.jsx b/src/pages/Profile/ProfilePage.jsx index aaa1338..b2602d0 100644 --- a/src/pages/Profile/ProfilePage.jsx +++ b/src/pages/Profile/ProfilePage.jsx @@ -31,12 +31,12 @@ function ProfilePage() {

Mail : {user.email}

-

Téléphone : {user.phone}

+

Téléphone : {user.phone === null ? "Pas de numéro enregistré" : user.phone}

-

Vos Événements :

+

Tâches :

{user.tasks && user.tasks.length > 0 ? ( user.tasks.map((task, index) => ( From fa9298a3343aa356c7a1f490466f06aef24f36af Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 15:05:29 +0100 Subject: [PATCH 41/48] Create PageNotFound.jsx --- src/pages/PageNotFound/PageNotFound.jsx | 10 ++++++++++ src/pages/PageNotFound/PageNotFound.module.css | 0 src/router.js | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 src/pages/PageNotFound/PageNotFound.jsx create mode 100644 src/pages/PageNotFound/PageNotFound.module.css diff --git a/src/pages/PageNotFound/PageNotFound.jsx b/src/pages/PageNotFound/PageNotFound.jsx new file mode 100644 index 0000000..35299a6 --- /dev/null +++ b/src/pages/PageNotFound/PageNotFound.jsx @@ -0,0 +1,10 @@ +import Background from "../../components/background/background.jsx"; + +export default function PageNotFound() { + + return + +

404

+ +
+} \ No newline at end of file diff --git a/src/pages/PageNotFound/PageNotFound.module.css b/src/pages/PageNotFound/PageNotFound.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/router.js b/src/router.js index 25c91b9..7b34c16 100644 --- a/src/router.js +++ b/src/router.js @@ -9,6 +9,7 @@ import ProfilePage from "./pages/Profile/ProfilePage"; import EventsPage from "./pages/Events/EventsPage.jsx"; import ValidationErrorPage from "./pages/waitValidationPage/ValidationErrorPage.jsx"; import VolunteerProfilePage from "./pages/VolunteerProfile/VolunteerProfilePage.jsx"; +import PageNotFound from "./pages/PageNotFound/PageNotFound.jsx"; const router = createBrowserRouter([ { @@ -23,6 +24,10 @@ const router = createBrowserRouter([ path: "/error/validation", Component: ValidationErrorPage }, + { + path: "/*", + Component: PageNotFound, + }, { path: "/", Component: Layout, From 883d19d7c4026d48a6c101f5a7d4640c20a4981f Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 15:10:58 +0100 Subject: [PATCH 42/48] Update PageNotFound.jsx --- src/pages/PageNotFound/PageNotFound.jsx | 18 ++++++++-- .../PageNotFound/PageNotFound.module.css | 33 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/pages/PageNotFound/PageNotFound.jsx b/src/pages/PageNotFound/PageNotFound.jsx index 35299a6..27b8630 100644 --- a/src/pages/PageNotFound/PageNotFound.jsx +++ b/src/pages/PageNotFound/PageNotFound.jsx @@ -1,10 +1,24 @@ import Background from "../../components/background/background.jsx"; +import styles from "./PageNotFound.module.css" +import { useNavigate } from "react-router"; export default function PageNotFound() { + const navigate = useNavigate(); + return +
+

Page non trouvée

+
+

+ Désolé, la page que vous recherchez n’existe pas ou n’est plus disponible.
+ Vous pouvez :
+ - Vérifier l’URL pour une éventuelle erreur de saisie.
+ - Revenir à l’accueil navigate("/")} className={styles.redirectSpan}>ici.
-

404

- +

+

Contact : contact@example.com

+
+
} \ No newline at end of file diff --git a/src/pages/PageNotFound/PageNotFound.module.css b/src/pages/PageNotFound/PageNotFound.module.css index e69de29..70e36f9 100644 --- a/src/pages/PageNotFound/PageNotFound.module.css +++ b/src/pages/PageNotFound/PageNotFound.module.css @@ -0,0 +1,33 @@ +.title { + color: white; + font-size: xx-large; + margin-bottom: 20px; +} + +.content { + display: flex; + flex-direction: column; + z-index: 2; + padding: 10px; +} + +.container { + padding: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 15px; + + p { + font-size: large; + } +} +.redirectSpan { + color: blue; + text-decoration: underline; +} + +.redirectSpan:hover { + cursor: pointer; +} \ No newline at end of file From c2f4c9fa55afe3289df33f5b694e9f9a8aec31a1 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 15:20:51 +0100 Subject: [PATCH 43/48] Redirect to 404 page if user not found --- .../VolunteerProfile/VolunteerProfilePage.jsx | 16 ++++++++++++---- src/router.js | 4 ++++ src/utils/users/getUserById.js | 9 ++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx index 06b4ee3..1f18805 100644 --- a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx +++ b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx @@ -4,20 +4,28 @@ import { useEffect, useState } from "react"; import getUserById from "../../utils/users/getUserById.js"; import formatDate from "../../utils/date/formatDate.js"; import Task from "../../components/Task/Task.jsx"; +import { useNavigate } from "react-router"; export default function VolunteerProfilePage() { const params = useParams(); const id = params.id; + const navigate = useNavigate(); + const [user, setUser] = useState({}); useEffect(() => { (async () => { - const data = await getUserById(id); - setUser(data); - }) () - }, []); + const result = await getUserById(id); + if (result?.error === 'not_found') { + navigate("/404"); + } else { + setUser(result); + } + })(); + }, [id]); + return
diff --git a/src/router.js b/src/router.js index 7b34c16..e9b0c56 100644 --- a/src/router.js +++ b/src/router.js @@ -28,6 +28,10 @@ const router = createBrowserRouter([ path: "/*", Component: PageNotFound, }, + { + path: "/404", + Component: PageNotFound, + }, { path: "/", Component: Layout, diff --git a/src/utils/users/getUserById.js b/src/utils/users/getUserById.js index 59af94a..1fad659 100644 --- a/src/utils/users/getUserById.js +++ b/src/utils/users/getUserById.js @@ -1,4 +1,4 @@ -export default async function getUserById (id) { +export default async function getUserById(id) { try { const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/${id}`, { method: 'GET', @@ -9,12 +9,15 @@ export default async function getUserById (id) { }); if (!res.ok) { + if (res.status === 404) { + return { error: 'not_found' }; + } throw new Error(`Erreur serveur : ${res.status}`); } return await res.json(); } catch (err) { console.error('Erreur :', err); - return null; + return { error: 'server_error' }; } -} \ No newline at end of file +} From ef948432d1f4a257735f079e44bd33bd3f08446f Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 15:33:37 +0100 Subject: [PATCH 44/48] Show admin link if user is admin --- src/components/Header/Header.jsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 74bfc31..d467539 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -1,7 +1,8 @@ import styles from "./Header.module.css" import { Link, NavLink } from "react-router"; -import { useEffect, useRef, useState } from "react"; +import {useContext, useEffect, useRef, useState} from "react"; import getUserNotifications from "../../utils/getUserNotifications.js"; +import {AuthContext} from "../../contexts/auth/AuthContext.js"; function Header() { const [notificationMenu, setnotificationMenu] = useState(false); @@ -10,6 +11,7 @@ function Header() { const [notifications, setNotifications] = useState([{"content" : "ok"}, {"content" : "pourquoi pas antoine"}]); const notificationRef = useRef(null); + const { user } = useContext(AuthContext); useEffect(() => { @@ -53,6 +55,9 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles + {user.isAdmin && isActive ? styles.activeLink : styles.link}> + Administration + }
@@ -84,6 +89,9 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles + {user.isAdmin && isActive ? styles.activeLink : styles.link}> + Administration + } From c0ad7f3146cccf9c628796a0cb29438ecc966924 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 17 Dec 2025 16:12:32 +0100 Subject: [PATCH 45/48] adapt incompleteEvents responsive --- .../IncompleteEvent/IncompleteEvent.jsx | 25 ++++-- .../IncompleteEvent.module.css | 89 +++++++++++++++---- .../PendingMembers/PendingMembers.module.css | 10 ++- src/components/chart/ParticipationChart.jsx | 2 +- .../chart/ParticipationChart.module.css | 47 ++++++++-- src/layout.jsx | 2 +- .../StatPage.jsx => Admin/AdminPage.jsx} | 6 +- .../AdminPage.module.css} | 0 src/router.js | 9 +- 9 files changed, 146 insertions(+), 44 deletions(-) rename src/pages/{Stat/StatPage.jsx => Admin/AdminPage.jsx} (88%) rename src/pages/{Stat/StatPage.module.css => Admin/AdminPage.module.css} (100%) diff --git a/src/components/IncompleteEvent/IncompleteEvent.jsx b/src/components/IncompleteEvent/IncompleteEvent.jsx index 84dc2a9..b8e3355 100644 --- a/src/components/IncompleteEvent/IncompleteEvent.jsx +++ b/src/components/IncompleteEvent/IncompleteEvent.jsx @@ -3,13 +3,18 @@ import styles from "./IncompleteEvent.module.css"; function IncompleteEvent() { const incompleteEvents = [ - { title: "Événement A", tasks: "Préparation des flyers" }, - { title: "Événement B", tasks: "Réservation de la salle" }, - { title: "Événement C", tasks: "Communication sur les réseaux" }, - { title: "Événement D", tasks: "Communication sur les réseaux" }, - { title: "Événement E", tasks: "Communication sur les réseaux" }, - { title: "Événement F", tasks: "Communication sur les réseaux" }, - ]; + { title: "Événement A", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm,Communication sur les réseaux", + "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm]"] }, + { title: "Événement B", tasks: ["Réservation de la salle", "Vérification du matériel"] }, + { title: "Événement C", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm"] }, + { title: "Événement D", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm"] }, + { title: "Événement E", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm,Communication sur les réseaux", + "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm]"] }, + { title: "Événement F", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm,Communication sur les réseaux", + "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm]"] }, + { title: "Événement G", tasks: ["Communication sur les réseaux", "Enormément de comm", "Toujours + de comm,Communication sur les réseaux", + "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm","Communication sur les réseaux", "Enormément de comm", "Toujours + de comm]"] }, +]; return (
@@ -18,7 +23,11 @@ function IncompleteEvent() { {incompleteEvents.map((event, index) => (

{event.title}

-

{event.tasks}

+
    + {event.tasks.map((task, taskIndex) => ( +
  • {task}
  • + ))} +
))}
diff --git a/src/components/IncompleteEvent/IncompleteEvent.module.css b/src/components/IncompleteEvent/IncompleteEvent.module.css index e56e1f1..b3f1d70 100644 --- a/src/components/IncompleteEvent/IncompleteEvent.module.css +++ b/src/components/IncompleteEvent/IncompleteEvent.module.css @@ -2,7 +2,7 @@ width: 100%; } -.rightBlock > h2 { +.rightBlock>h2 { font-size: 29px; } @@ -10,13 +10,23 @@ display: flex; flex-direction: row; gap: 10px; - margin-top: 15px; + margin-top: 5px; overflow-x: auto; overflow-y: hidden; padding-bottom: 10px; scroll-behavior: smooth; } +.eventCard ul { + align-items: center; + margin-left: 8%; +} + +.eventCard ul li { + text-align: left; + list-style-type: circle; +} + .eventsContainer::-webkit-scrollbar { height: 8px; } @@ -38,7 +48,9 @@ .eventCard { min-width: calc((100% - 20px) / 3); max-width: calc((100% - 20px) / 3); - flex-shrink: 0; + min-height: 250px; + max-height: 250px; + overflow-y: auto; padding: 10px; text-align: center; padding-bottom: 200px; @@ -46,31 +58,78 @@ opacity: 0; transform: translateX(20px); animation: slideInEvent 1s ease forwards; + + flex-shrink: 1; + padding: 10px; + text-align: center; + box-sizing: border-box; } -.eventCard:nth-child(1) { animation-delay: 0s; } -.eventCard:nth-child(2) { animation-delay: 0.1s; } -.eventCard:nth-child(3) { animation-delay: 0.2s; } -.eventCard:nth-child(4) { animation-delay: 0.3s; } -.eventCard:nth-child(5) { animation-delay: 0.4s; } -.eventCard:nth-child(6) { animation-delay: 0.5s; } +.eventCard:nth-child(1) { + animation-delay: 0s; +} -.eventCard > h3 { +.eventCard:nth-child(2) { + animation-delay: 0.1s; +} + +.eventCard:nth-child(3) { + animation-delay: 0.2s; +} + +.eventCard:nth-child(4) { + animation-delay: 0.3s; +} + +.eventCard:nth-child(5) { + animation-delay: 0.4s; +} + +.eventCard:nth-child(6) { + animation-delay: 0.5s; +} + +.eventCard>h3 { font-size: 24px; } @keyframes slideInEvent { - from { opacity: 0; transform: translateX(20px); } - to { opacity: 1; transform: translateX(0); } + from { + opacity: 0; + transform: translateX(20px); + } + + to { + opacity: 1; + transform: translateX(0); + } } @media screen and (max-width: 760px) { .eventCard { - width: 100%; - height: 200px; + min-width: 100%; + min-height: 200px; + max-height: fit-content; + padding-bottom: 0px; } .eventCard h3 { font-size: 17px; } -} + + .eventsContainer { + display: flex; + flex-direction: column; + gap: 10px; + max-height: 300px; + margin-top: 15px; + height: fit-content; + overflow-y: auto; + padding-bottom: 0px; + scroll-behavior: smooth; + } + + .rightBlock>h2 { + font-size: 18px; + } +} \ No newline at end of file diff --git a/src/components/PendingMembers/PendingMembers.module.css b/src/components/PendingMembers/PendingMembers.module.css index 35a892e..9eaef39 100644 --- a/src/components/PendingMembers/PendingMembers.module.css +++ b/src/components/PendingMembers/PendingMembers.module.css @@ -10,13 +10,14 @@ display: flex; flex-direction: column; gap: 10px; - margin-top: 0px; + margin-top: 20px; max-height: 185px; overflow-y: auto; padding-right: 5px; scroll-behavior: smooth; } + .membersContainer::-webkit-scrollbar { width: 8px; } @@ -70,4 +71,11 @@ .membersContainer { max-height: 200px; } + .rightBlock > h2{ + font-size:18px; + } + + .memberCard p{ + font-size: 15px; + } } diff --git a/src/components/chart/ParticipationChart.jsx b/src/components/chart/ParticipationChart.jsx index 7648bf1..7ebd731 100644 --- a/src/components/chart/ParticipationChart.jsx +++ b/src/components/chart/ParticipationChart.jsx @@ -8,7 +8,7 @@ Chart.register(ArcElement); function participationChart() { const [selected, setSelected] = useState("3"); - const [participationRate, setParticipationRate] = useState(89); + const [participationRate, setParticipationRate] = useState(78); const chartData = { labels: ["Progress", "Background"], diff --git a/src/components/chart/ParticipationChart.module.css b/src/components/chart/ParticipationChart.module.css index 762ae0c..7fa3515 100644 --- a/src/components/chart/ParticipationChart.module.css +++ b/src/components/chart/ParticipationChart.module.css @@ -3,7 +3,9 @@ display: flex; flex-direction: column; align-items: center; - height: fit-content; + height: calc(100vh - 260px); + /* Exemple: calc(100vh - 60px) */ + margin-bottom: auto; } .participationHeader { @@ -14,6 +16,8 @@ .partiText { display: flex; + width: 100%; + flex-direction: column; align-items: center; justify-content: center; margin-bottom: 2%; @@ -29,6 +33,8 @@ .chartContainer { max-width: 80%; + width: 400px; + height: auto; margin: 0 auto; position: relative; animation: slideEvent2 2s; @@ -54,13 +60,27 @@ } @keyframes slideEvent2 { - from { opacity: 0; transform: translateX(-20px); } - to { opacity: 1; transform: translateX(0); } + from { + opacity: 0; + transform: translateX(-20px); + } + + to { + opacity: 1; + transform: translateX(0); + } } @keyframes slideInEvent { - from { opacity: 0; transform: translateX(20px); } - to { opacity: 1; transform: translateX(0); } + from { + opacity: 0; + transform: translateX(20px); + } + + to { + opacity: 1; + transform: translateX(0); + } } .formControl { @@ -83,7 +103,18 @@ .partiText label { text-align: center; } - .leftBlock{ - width:100%; + + .leftBlock { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + height: fit-content; + margin-bottom: auto; + margin-top: 30px; } -} + .chartContainer{ + height:fit-content; + } + +} \ No newline at end of file diff --git a/src/layout.jsx b/src/layout.jsx index 4689a4e..339734c 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -12,7 +12,7 @@ function Layout(){ const { user, loading } = useContext(AuthContext); if (loading) return

Loading

; - if (!user) return ; + // if (!user) return ; return (
diff --git a/src/pages/Stat/StatPage.jsx b/src/pages/Admin/AdminPage.jsx similarity index 88% rename from src/pages/Stat/StatPage.jsx rename to src/pages/Admin/AdminPage.jsx index 6cb0816..71ad4be 100644 --- a/src/pages/Stat/StatPage.jsx +++ b/src/pages/Admin/AdminPage.jsx @@ -1,10 +1,10 @@ import React, { useState } from "react"; -import styles from "./StatPage.module.css"; +import styles from "./AdminPage.module.css"; import ParticipationChart from "../../components/chart/ParticipationChart.jsx"; import IncompleteEvents from "../../components/IncompleteEvent/IncompleteEvent.jsx"; import PendingMembers from "../../components/PendingMembers/PendingMembers.jsx"; -function StatPage() { +function AdminPage() { const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); @@ -23,4 +23,4 @@ function StatPage() { ); } -export default StatPage; +export default AdminPage; diff --git a/src/pages/Stat/StatPage.module.css b/src/pages/Admin/AdminPage.module.css similarity index 100% rename from src/pages/Stat/StatPage.module.css rename to src/pages/Admin/AdminPage.module.css diff --git a/src/router.js b/src/router.js index 02af71a..f54d582 100644 --- a/src/router.js +++ b/src/router.js @@ -2,12 +2,11 @@ import { createBrowserRouter } from "react-router"; import Layout from "./layout.jsx"; import HomePage from "./pages/Home/HomePage"; import LoginPage from "./pages/Login/LoginPage"; -import StatPage from "./pages/Stat/StatPage"; import RegisterPage from "./pages/Register/RegisterPage.jsx"; import VolunteersPage from "./pages/Volunteers/VolunteersPage"; import ProfilePage from "./pages/Profile/ProfilePage"; import EventsPage from "./pages/Events/EventsPage.jsx"; - +import AdminPage from "./pages/Admin/AdminPage.jsx"; const router = createBrowserRouter([ { @@ -28,7 +27,7 @@ const router = createBrowserRouter([ }, { path: "/admin", - Component:StatPage, + Component:AdminPage, }, { path:"/profile", @@ -42,10 +41,6 @@ const router = createBrowserRouter([ path: "/volunteers", Component: VolunteersPage, }, - { - path: "/stat", - Component:StatPage, - }, ] } ]) From 6bcc7e44961f7fccc6cfce95fee0a1af662f6a27 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 17 Dec 2025 16:57:16 +0100 Subject: [PATCH 46/48] Redirect if user is not admin --- src/pages/Admin/AdminPage.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/Admin/AdminPage.jsx b/src/pages/Admin/AdminPage.jsx index 71ad4be..da36ac4 100644 --- a/src/pages/Admin/AdminPage.jsx +++ b/src/pages/Admin/AdminPage.jsx @@ -1,13 +1,22 @@ -import React, { useState } from "react"; +import { useState, useContext } from "react"; import styles from "./AdminPage.module.css"; import ParticipationChart from "../../components/chart/ParticipationChart.jsx"; import IncompleteEvents from "../../components/IncompleteEvent/IncompleteEvent.jsx"; import PendingMembers from "../../components/PendingMembers/PendingMembers.jsx"; +import { AuthContext } from "../../contexts/auth/AuthContext.js"; +import { useNavigate } from "react-router"; + function AdminPage() { + + const { user } = useContext(AuthContext); + const navigate = useNavigate(); + const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); + if(!user.isAdmin) navigate("/"); + return (
Date: Wed, 17 Dec 2025 16:59:13 +0100 Subject: [PATCH 47/48] Fix .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index bd7187d..0fc3e15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.env + # Logs logs *.log From 919b978f57a88d306ec7a8e0b9c6f8da3bd6b2ad Mon Sep 17 00:00:00 2001 From: p2405951 Date: Sat, 27 Dec 2025 17:30:25 +0100 Subject: [PATCH 48/48] withdraw auth for test --- src/components/Header/Header.jsx | 8 ++------ src/layout.jsx | 4 ++-- src/pages/Admin/AdminPage.jsx | 2 +- src/pages/Profile/ProfilePage.jsx | 1 - 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index d467539..873c250 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -55,9 +55,7 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles - {user.isAdmin && isActive ? styles.activeLink : styles.link}> - Administration - } +
@@ -89,9 +87,7 @@ function Header() { isActive ? styles.activeLink : styles.link}> Bénévoles - {user.isAdmin && isActive ? styles.activeLink : styles.link}> - Administration - } + diff --git a/src/layout.jsx b/src/layout.jsx index 4fa0991..2bfae90 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -11,9 +11,9 @@ function Layout(){ const { user, loading } = useContext(AuthContext); - if (loading) return

Loading

; + /* if (loading) return

Loading

; if (!user) return ; - if(user && user.validate === 0) return ; + if(user && user.validate === 0) return ;*/ return (
diff --git a/src/pages/Admin/AdminPage.jsx b/src/pages/Admin/AdminPage.jsx index da36ac4..7682bb1 100644 --- a/src/pages/Admin/AdminPage.jsx +++ b/src/pages/Admin/AdminPage.jsx @@ -15,7 +15,7 @@ function AdminPage() { const [selected, setSelected] = useState("3"); const [participationRate, setParticipationRate] = useState(89); - if(!user.isAdmin) navigate("/"); + /*if(!user.isAdmin) navigate("/");*/ return (
diff --git a/src/pages/Profile/ProfilePage.jsx b/src/pages/Profile/ProfilePage.jsx index b2602d0..a47e87c 100644 --- a/src/pages/Profile/ProfilePage.jsx +++ b/src/pages/Profile/ProfilePage.jsx @@ -8,7 +8,6 @@ import SettingsModal from "../../components/SettingsModal/SettingsModal.jsx"; function ProfilePage() { const { user } = useContext(AuthContext); - return (