From 2f0bc4770138e36a6adf1866eed522e46e595c0f Mon Sep 17 00:00:00 2001
From: Sai4158 <116776995+Sai4158@users.noreply.github.com>
Date: Sun, 13 Jul 2025 23:52:43 -0400
Subject: [PATCH 1/4] Added UI changes, auto suggestions and custom alerts
Changed UI and section layout
latest users and the new users tab and page indexing
auto suggestion for filling username and challenge management
Custom alerts instead of window default alerts User interface and section layout have been updated.
---
package-lock.json | 1281 +++++++++++++++++++++++++++-
src/pages/moderation.jsx | 1698 +++++++++++++++++++++++++++++++-------
yarn.lock | 941 +++++++++++++++++++--
3 files changed, 3550 insertions(+), 370 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 5be40a9a..ac204637 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2066,6 +2066,614 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@firebase/ai": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-1.4.1.tgz",
+ "integrity": "sha512-bcusQfA/tHjUjBTnMx6jdoPMpDl3r8K15Z+snHz9wq0Foox0F/V+kNLXucEOHoTL2hTc9l+onZCyBJs2QoIC3g==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics": {
+ "version": "0.10.17",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.17.tgz",
+ "integrity": "sha512-n5vfBbvzduMou/2cqsnKrIes4auaBjdhg8QNA2ZQZ59QgtO2QiwBaXQZQE4O4sgB0Ds1tvLgUUkY+pwzu6/xEg==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/installations": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-compat": {
+ "version": "0.2.23",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.23.tgz",
+ "integrity": "sha512-3AdO10RN18G5AzREPoFgYhW6vWXr3u+OYQv6pl3CX6Fky8QRk0AHurZlY3Q1xkXO0TDxIsdhO3y65HF7PBOJDw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/analytics": "0.10.17",
+ "@firebase/analytics-types": "0.8.3",
+ "@firebase/component": "0.6.18",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz",
+ "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==",
+ "peer": true
+ },
+ "node_modules/@firebase/app": {
+ "version": "0.13.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.13.2.tgz",
+ "integrity": "sha512-jwtMmJa1BXXDCiDx1vC6SFN/+HfYG53UkfJa6qeN5ogvOunzbFDO3wISZy5n9xgYFUrEP6M7e8EG++riHNTv9w==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-check": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.10.1.tgz",
+ "integrity": "sha512-MgNdlms9Qb0oSny87pwpjKush9qUwCJhfmTJHDfrcKo4neLGiSeVE4qJkzP7EQTIUFKp84pbTxobSAXkiuQVYQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-compat": {
+ "version": "0.3.26",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.26.tgz",
+ "integrity": "sha512-PkX+XJMLDea6nmnopzFKlr+s2LMQGqdyT2DHdbx1v1dPSqOol2YzgpgymmhC67vitXVpNvS3m/AiWQWWhhRRPQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app-check": "0.10.1",
+ "@firebase/app-check-types": "0.5.3",
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-interop-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz",
+ "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==",
+ "peer": true
+ },
+ "node_modules/@firebase/app-check-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz",
+ "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==",
+ "peer": true
+ },
+ "node_modules/@firebase/app-compat": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.4.2.tgz",
+ "integrity": "sha512-LssbyKHlwLeiV8GBATyOyjmHcMpX/tFjzRUCS1jnwGAew1VsBB4fJowyS5Ud5LdFbYpJeS+IQoC+RQxpK7eH3Q==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app": "0.13.2",
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-types": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
+ "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
+ "peer": true
+ },
+ "node_modules/@firebase/auth-compat": {
+ "version": "0.5.28",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.28.tgz",
+ "integrity": "sha512-HpMSo/cc6Y8IX7bkRIaPPqT//Jt83iWy5rmDWeThXQCAImstkdNo3giFLORJwrZw2ptiGkOij64EH1ztNJzc7Q==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/auth": "1.10.8",
+ "@firebase/auth-types": "0.13.0",
+ "@firebase/component": "0.6.18",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/auth-compat/node_modules/@firebase/auth": {
+ "version": "1.10.8",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.10.8.tgz",
+ "integrity": "sha512-GpuTz5ap8zumr/ocnPY57ZanX02COsXloY6Y/2LYPAuXYiaJRf6BAGDEdRq1BMjP93kqQnKNuKZUTMZbQ8MNYA==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-interop-types": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz",
+ "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==",
+ "peer": true
+ },
+ "node_modules/@firebase/auth-types": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz",
+ "integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==",
+ "peer": true,
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/component": {
+ "version": "0.6.18",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.18.tgz",
+ "integrity": "sha512-n28kPCkE2dL2U28fSxZJjzPPVpKsQminJ6NrzcKXAI0E/lYC8YhfwpyllScqVEvAI3J2QgJZWYgrX+1qGI+SQQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/data-connect": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.10.tgz",
+ "integrity": "sha512-VMVk7zxIkgwlVQIWHOKFahmleIjiVFwFOjmakXPd/LDgaB/5vzwsB5DWIYo+3KhGxWpidQlR8geCIn39YflJIQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/database": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.20.tgz",
+ "integrity": "sha512-H9Rpj1pQ1yc9+4HQOotFGLxqAXwOzCHsRSRjcQFNOr8lhUt6LeYjf0NSRL04sc4X0dWe8DsCvYKxMYvFG/iOJw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-compat": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.11.tgz",
+ "integrity": "sha512-itEsHARSsYS95+udF/TtIzNeQ0Uhx4uIna0sk4E0wQJBUnLc/G1X6D7oRljoOuwwCezRLGvWBRyNrugv/esOEw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/database": "1.0.20",
+ "@firebase/database-types": "1.0.15",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-types": {
+ "version": "1.0.15",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.15.tgz",
+ "integrity": "sha512-XWHJ0VUJ0k2E9HDMlKxlgy/ZuTa9EvHCGLjaKSUvrQnwhgZuRU5N3yX6SZ+ftf2hTzZmfRkv+b3QRvGg40bKNw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app-types": "0.9.3",
+ "@firebase/util": "1.12.1"
+ }
+ },
+ "node_modules/@firebase/firestore": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.8.0.tgz",
+ "integrity": "sha512-QSRk+Q1/CaabKyqn3C32KSFiOdZpSqI9rpLK5BHPcooElumOBooPFa6YkDdiT+/KhJtel36LdAacha9BptMj2A==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "@firebase/webchannel-wrapper": "1.0.3",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-compat": {
+ "version": "0.3.53",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.53.tgz",
+ "integrity": "sha512-qI3yZL8ljwAYWrTousWYbemay2YZa+udLWugjdjju2KODWtLG94DfO4NALJgPLv8CVGcDHNFXoyQexdRA0Cz8Q==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/firestore": "4.8.0",
+ "@firebase/firestore-types": "3.0.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz",
+ "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==",
+ "peer": true,
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/functions": {
+ "version": "0.12.9",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.9.tgz",
+ "integrity": "sha512-FG95w6vjbUXN84Ehezc2SDjGmGq225UYbHrb/ptkRT7OTuCiQRErOQuyt1jI1tvcDekdNog+anIObihNFz79Lg==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.18",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-compat": {
+ "version": "0.3.26",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.26.tgz",
+ "integrity": "sha512-A798/6ff5LcG2LTWqaGazbFYnjBW8zc65YfID/en83ALmkhu2b0G8ykvQnLtakbV9ajrMYPn7Yc/XcYsZIUsjA==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/functions": "0.12.9",
+ "@firebase/functions-types": "0.6.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-types": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz",
+ "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==",
+ "peer": true
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.18",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.18.tgz",
+ "integrity": "sha512-NQ86uGAcvO8nBRwVltRL9QQ4Reidc/3whdAasgeWCPIcrhOKDuNpAALa6eCVryLnK14ua2DqekCOX5uC9XbU/A==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/util": "1.12.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-compat": {
+ "version": "0.2.18",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.18.tgz",
+ "integrity": "sha512-aLFohRpJO5kKBL/XYL4tN+GdwEB/Q6Vo9eZOM/6Kic7asSUgmSfGPpGUZO1OAaSRGwF4Lqnvi1f/f9VZnKzChw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/installations": "0.6.18",
+ "@firebase/installations-types": "0.5.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz",
+ "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==",
+ "peer": true,
+ "peerDependencies": {
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz",
+ "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==",
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.22",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.22.tgz",
+ "integrity": "sha512-GJcrPLc+Hu7nk+XQ70Okt3M1u1eRr2ZvpMbzbc54oTPJZySHcX9ccZGVFcsZbSZ6o1uqumm8Oc7OFkD3Rn1/og==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/installations": "0.6.18",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.12.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-compat": {
+ "version": "0.2.22",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.22.tgz",
+ "integrity": "sha512-5ZHtRnj6YO6f/QPa/KU6gryjmX4Kg33Kn4gRpNU6M1K47Gm8kcQwPkX7erRUYEH1mIWptfvjvXMHWoZaWjkU7A==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/messaging": "0.12.22",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz",
+ "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==",
+ "peer": true
+ },
+ "node_modules/@firebase/performance": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.7.tgz",
+ "integrity": "sha512-JTlTQNZKAd4+Q5sodpw6CN+6NmwbY72av3Lb6wUKTsL7rb3cuBIhQSrslWbVz0SwK3x0ZNcqX24qtRbwKiv+6w==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/installations": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0",
+ "web-vitals": "^4.2.4"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-compat": {
+ "version": "0.2.20",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.20.tgz",
+ "integrity": "sha512-XkFK5NmOKCBuqOKWeRgBUFZZGz9SzdTZp4OqeUg+5nyjapTiZ4XoiiUL8z7mB2q+63rPmBl7msv682J3rcDXIQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/performance": "0.7.7",
+ "@firebase/performance-types": "0.2.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz",
+ "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==",
+ "peer": true
+ },
+ "node_modules/@firebase/remote-config": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.6.5.tgz",
+ "integrity": "sha512-fU0c8HY0vrVHwC+zQ/fpXSqHyDMuuuglV94VF6Yonhz8Fg2J+KOowPGANM0SZkLvVOYpTeWp3ZmM+F6NjwWLnw==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/installations": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.18",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.18.tgz",
+ "integrity": "sha512-YiETpldhDy7zUrnS8e+3l7cNs0sL7+tVAxvVYU0lu7O+qLHbmdtAxmgY+wJqWdW2c9nDvBFec7QiF58pEUu0qQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/remote-config": "0.6.5",
+ "@firebase/remote-config-types": "0.4.0",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-types": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz",
+ "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==",
+ "peer": true
+ },
+ "node_modules/@firebase/storage": {
+ "version": "0.13.14",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.14.tgz",
+ "integrity": "sha512-xTq5ixxORzx+bfqCpsh+o3fxOsGoDjC1nO0Mq2+KsOcny3l7beyBhP/y1u5T6mgsFQwI1j6oAkbT5cWdDBx87g==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-compat": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.24.tgz",
+ "integrity": "sha512-XHn2tLniiP7BFKJaPZ0P8YQXKiVJX+bMyE2j2YWjYfaddqiJnROJYqSomwW6L3Y+gZAga35ONXUJQju6MB6SOQ==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/storage": "0.13.14",
+ "@firebase/storage-types": "0.8.3",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz",
+ "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==",
+ "peer": true,
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.12.1.tgz",
+ "integrity": "sha512-zGlBn/9Dnya5ta9bX/fgEoNC3Cp8s6h+uYPYaDieZsFOAdHP/ExzQ/eaDgxD3GOROdPkLKpvKY0iIzr9adle0w==",
+ "hasInstallScript": true,
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/webchannel-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz",
+ "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==",
+ "peer": true
+ },
"node_modules/@floating-ui/core": {
"version": "1.6.9",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
@@ -2167,6 +2775,37 @@
"resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz",
"integrity": "sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw=="
},
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
+ "peer": true,
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ },
+ "engines": {
+ "node": "^8.13.0 || >=10.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.15",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
+ "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "peer": true,
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@headlessui/react": {
"version": "1.7.15",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz",
@@ -3031,6 +3670,70 @@
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "peer": true,
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "peer": true
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "peer": true
+ },
"node_modules/@puppeteer/browsers": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz",
@@ -3507,10 +4210,30 @@
"@types/ms": "*"
}
},
+ "node_modules/@types/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "peer": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "peer": true,
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
"node_modules/@types/estree": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
- "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="
},
"node_modules/@types/estree-jsx": {
"version": "1.0.5",
@@ -4032,6 +4755,152 @@
}
}
},
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "peer": true,
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "peer": true,
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "peer": true
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "peer": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
"node_modules/@webcontainer/api": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@webcontainer/api/-/api-1.5.3.tgz",
@@ -4042,6 +4911,18 @@
"resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
},
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "peer": true
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "peer": true
+ },
"node_modules/accessor-fn": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
@@ -4051,9 +4932,9 @@
}
},
"node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"bin": {
"acorn": "bin/acorn"
},
@@ -4061,6 +4942,18 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.3.tgz",
+ "integrity": "sha512-jtKLnfoOzm28PazuQ4dVBcE9Jeo6ha1GAJvq3N0LlNOszmTfx+wSycBehn+FN0RnyeR77IBxN/qVYMw0Rlj0Xw==",
+ "peer": true,
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@@ -4965,6 +5858,15 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "peer": true,
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
"node_modules/chromium-bidi": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz",
@@ -6029,6 +6931,19 @@
"node": ">=10.0.0"
}
},
+ "node_modules/enhanced-resolve": {
+ "version": "5.18.2",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
+ "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
+ "peer": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -6134,6 +7049,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "peer": true
+ },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
@@ -6689,7 +7610,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"estraverse": "^5.2.0"
@@ -6736,6 +7656,15 @@
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"license": "MIT"
},
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -6842,6 +7771,18 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "peer": true,
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@@ -6941,6 +7882,66 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/firebase": {
+ "version": "11.10.0",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.10.0.tgz",
+ "integrity": "sha512-nKBXoDzF0DrXTBQJlZa+sbC5By99ysYU1D6PkMRYknm0nCW7rJly47q492Ht7Ndz5MeYSBuboKuhS1e6mFC03w==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/ai": "1.4.1",
+ "@firebase/analytics": "0.10.17",
+ "@firebase/analytics-compat": "0.2.23",
+ "@firebase/app": "0.13.2",
+ "@firebase/app-check": "0.10.1",
+ "@firebase/app-check-compat": "0.3.26",
+ "@firebase/app-compat": "0.4.2",
+ "@firebase/app-types": "0.9.3",
+ "@firebase/auth": "1.10.8",
+ "@firebase/auth-compat": "0.5.28",
+ "@firebase/data-connect": "0.3.10",
+ "@firebase/database": "1.0.20",
+ "@firebase/database-compat": "2.0.11",
+ "@firebase/firestore": "4.8.0",
+ "@firebase/firestore-compat": "0.3.53",
+ "@firebase/functions": "0.12.9",
+ "@firebase/functions-compat": "0.3.26",
+ "@firebase/installations": "0.6.18",
+ "@firebase/installations-compat": "0.2.18",
+ "@firebase/messaging": "0.12.22",
+ "@firebase/messaging-compat": "0.2.22",
+ "@firebase/performance": "0.7.7",
+ "@firebase/performance-compat": "0.2.20",
+ "@firebase/remote-config": "0.6.5",
+ "@firebase/remote-config-compat": "0.2.18",
+ "@firebase/storage": "0.13.14",
+ "@firebase/storage-compat": "0.3.24",
+ "@firebase/util": "1.12.1"
+ }
+ },
+ "node_modules/firebase/node_modules/@firebase/auth": {
+ "version": "1.10.8",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.10.8.tgz",
+ "integrity": "sha512-GpuTz5ap8zumr/ocnPY57ZanX02COsXloY6Y/2LYPAuXYiaJRf6BAGDEdRq1BMjP93kqQnKNuKZUTMZbQ8MNYA==",
+ "peer": true,
+ "dependencies": {
+ "@firebase/component": "0.6.18",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.12.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
"node_modules/flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -7293,6 +8294,12 @@
"node": ">= 6"
}
},
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "peer": true
+ },
"node_modules/globals": {
"version": "13.20.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
@@ -7772,6 +8779,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/http-parser-js": {
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
+ "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
+ "peer": true
+ },
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
@@ -8580,6 +9593,15 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"license": "MIT"
},
+ "node_modules/loader-runner": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+ "peer": true,
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
"node_modules/loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
@@ -8630,6 +9652,12 @@
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "peer": true
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -8647,6 +9675,12 @@
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
},
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "peer": true
+ },
"node_modules/longest-streak": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
@@ -9656,6 +10690,12 @@
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
},
+ "node_modules/monaco-editor": {
+ "version": "0.52.2",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
+ "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
+ "peer": true
+ },
"node_modules/motion-dom": {
"version": "11.18.1",
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz",
@@ -9734,6 +10774,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "peer": true
+ },
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
@@ -10815,6 +11861,30 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/protobufjs": {
+ "version": "7.5.3",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
+ "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==",
+ "hasInstallScript": true,
+ "peer": true,
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/proxy-agent": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
@@ -13275,6 +14345,15 @@
"node": ">=10.13.0"
}
},
+ "node_modules/tapable": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
+ "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/tar-fs": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz",
@@ -13827,6 +14906,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/typescript": {
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "devOptional": true,
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
"node_modules/typo-js": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.3.tgz",
@@ -14185,6 +15278,19 @@
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"license": "MIT"
},
+ "node_modules/watchpack": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
+ "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
+ "peer": true,
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
@@ -14194,12 +15300,173 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/web-vitals": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
+ "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==",
+ "peer": true
+ },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
+ "node_modules/webpack": {
+ "version": "5.100.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.1.tgz",
+ "integrity": "sha512-YJB/ESPUe2Locd0NKXmw72Dx8fZQk1gTzI6rc9TAT4+Sypbnhl8jd8RywB1bDsDF9Dy1RUR7gn3q/ZJTd0OZZg==",
+ "peer": true,
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.8",
+ "@types/json-schema": "^7.0.15",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.15.0",
+ "acorn-import-phases": "^1.0.3",
+ "browserslist": "^4.24.0",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.17.2",
+ "es-module-lexer": "^1.2.1",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.11",
+ "json-parse-even-better-errors": "^2.3.1",
+ "loader-runner": "^4.2.0",
+ "mime-types": "^2.1.27",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^4.3.2",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.3.11",
+ "watchpack": "^2.4.1",
+ "webpack-sources": "^3.3.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
+ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
+ "peer": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/webpack/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "peer": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/webpack/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "peer": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/webpack/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "peer": true
+ },
+ "node_modules/webpack/node_modules/schema-utils": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
+ "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
+ "peer": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "peer": true,
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
diff --git a/src/pages/moderation.jsx b/src/pages/moderation.jsx
index b4689c5e..a2f802fc 100644
--- a/src/pages/moderation.jsx
+++ b/src/pages/moderation.jsx
@@ -2,47 +2,360 @@ import React, { useEffect, useState } from 'react';
import {
ArrowRightIcon,
QuestionMarkCircleIcon,
+ ChevronLeftIcon,
+ ChevronRightIcon,
+ UserGroupIcon,
+ DocumentTextIcon,
+ ExclamationTriangleIcon,
+ ChartBarIcon,
} from '@heroicons/react/20/solid';
import Head from 'next/head';
import { StandardNav } from '@/components/StandardNav';
import { Footer } from '@/components/Footer';
-import { PracticeNav } from '@/components/practice/PracticeNav';
-import { Community } from '@/components/practice/community';
import request from '@/utils/request';
-import { MyTable } from '@/components/Table';
-import { TableHead, TableRow, TableHeader, TableCell, TableBody, Table } from "@/components/ui/table"
import ViewChallenge from '@/components/moderation/ViewChallenge';
import ViewReport from '@/components/moderation/ViewReport';
-export default function Competitions() {
+export default function Moderation() {
+ // Challenge states
const [selectedChallenges, setSelectedChallenges] = useState([]);
const [selectedId, setSelectedId] = useState(null);
const [pendingChallenges, setPendingChallenges] = useState([]);
const [challengeIsOpen, setChallengeIsOpen] = useState(false);
+ const [bonusPoints, setBonusPoints] = useState(0);
-
+ // Report states
const [reports, setReports] = useState([]);
-
-
- const [bonusPoints, setBonusPoints] = useState(0);
const [selectedReport, setSelectedReport] = useState(null);
const [reportIsOpen, setReportIsOpen] = useState(false);
-
- // get reports
- useEffect(() => {
- const fetchReports = async () => {
- const response = await request(process.env.NEXT_PUBLIC_API_URL + '/reports', "GET");
- setReports(response);
+ // User management states
+ const [users, setUsers] = useState([]);
+ const [currentUserPage, setCurrentUserPage] = useState(0);
+ const [totalUserPages, setTotalUserPages] = useState(0);
+ const [totalUsers, setTotalUsers] = useState(0);
+
+ // Recent activity states
+ const [recentComments, setRecentComments] = useState([]);
+ const [recentWriteups, setRecentWriteups] = useState([]);
+ const [recentLessons, setRecentLessons] = useState([]);
+
+ // Platform stats
+ const [stats, setStats] = useState(null);
+
+ // Active tab state
+ const [activeTab, setActiveTab] = useState('overview');
+
+ // Autocomplete states
+ const [userSuggestions, setUserSuggestions] = useState([]);
+ const [challengeSuggestions, setChallengeSuggestions] = useState([]);
+ const [showUserSuggestions, setShowUserSuggestions] = useState(false);
+ const [showChallengeSuggestions, setShowChallengeSuggestions] =
+ useState(false);
+ const [userSearchQuery, setUserSearchQuery] = useState('');
+ const [challengeSearchQuery, setChallengeSearchQuery] = useState('');
+
+ // Notification states
+ const [notification, setNotification] = useState(null);
+
+ // Notification helper function
+ const showNotification = (message, type = 'info') => {
+ const id = Date.now();
+ setNotification({ id, message, type });
+ };
+
+ // Notification component
+ const NotificationModal = () => {
+ if (!notification) return null;
+
+ const getNotificationIcon = () => {
+ switch (notification.type) {
+ case 'success':
+ return 'fas fa-check-circle';
+ case 'error':
+ return 'fas fa-exclamation-circle';
+ case 'warning':
+ return 'fas fa-exclamation-triangle';
+ default:
+ return 'fas fa-info-circle';
+ }
};
- fetchReports();
- }, []);
-
+
+ const icon = getNotificationIcon();
+
+ return (
+
+
setNotification(null)}
+ />
+
+
+
+
+
+
+
+ {notification.message}
+
+
+
setNotification(null)}
+ className="flex h-8 w-8 items-center justify-center rounded-lg text-gray-400 transition-all duration-200 hover:scale-110 hover:bg-neutral-700/50 hover:text-white active:scale-95"
+ >
+
+
+
+
+
+ );
+ };
+
+ // Fetch functions
+ const fetchReports = async () => {
+ try {
+ console.log('Fetching reports...');
+ const response = await request(
+ process.env.NEXT_PUBLIC_API_URL + '/reports',
+ 'GET'
+ );
+ console.log('Reports response:', response);
+ setReports(response || []);
+ } catch (error) {
+ console.error('Failed to fetch reports:', error);
+ setReports([]);
+ }
+ };
+
+ const fetchPendingChallenges = async () => {
+ try {
+ console.log('Fetching pending challenges...');
+ const response = await request(
+ process.env.NEXT_PUBLIC_API_URL + '/pending',
+ 'GET'
+ );
+ console.log('Pending challenges response:', response);
+ setPendingChallenges(response || []);
+ } catch (error) {
+ console.error('Failed to fetch pending challenges:', error);
+ setPendingChallenges([]);
+ }
+ };
+
+ const fetchUsers = async (page = 0) => {
+ try {
+ console.log('Fetching users for page:', page);
+ const url = `${process.env.NEXT_PUBLIC_API_URL}/admin/users?page=${page}&size=30&order=createdAt&ordertype=desc`;
+ console.log('Fetching from URL:', url);
+
+ const response = await request(url, 'GET');
+ console.log('Users API response:', response);
+
+ if (response === null) {
+ console.error('Request returned null - likely authentication issue');
+ setUsers([]);
+ setTotalUserPages(0);
+ setTotalUsers(0);
+ setCurrentUserPage(0);
+ return;
+ }
+
+ if (response && response.result) {
+ console.log('Setting users data:', response.result.length, 'users');
+ setUsers(response.result || []);
+ setTotalUserPages((response.lastPage || 0) + 1);
+ setTotalUsers(response.totalEntries || 0);
+ setCurrentUserPage(page);
+ } else {
+ console.error('Invalid response format:', response);
+ if (response && response.error) {
+ console.error('API Error:', response.error);
+ }
+ setUsers([]);
+ setTotalUserPages(0);
+ setTotalUsers(0);
+ setCurrentUserPage(0);
+ }
+ } catch (error) {
+ console.error('Failed to fetch users:', error);
+ setUsers([]);
+ setTotalUserPages(0);
+ setTotalUsers(0);
+ setCurrentUserPage(0);
+ }
+ };
+
+ const fetchRecentActivity = async () => {
+ try {
+ console.log('Fetching recent activity...');
+ const [commentsRes, writeupsRes, lessonsRes] = await Promise.all([
+ request(`${process.env.NEXT_PUBLIC_API_URL}/activity/comments`, 'GET'),
+ request(`${process.env.NEXT_PUBLIC_API_URL}/activity/writeups`, 'GET'),
+ request(`${process.env.NEXT_PUBLIC_API_URL}/activity/lessons`, 'GET'),
+ ]);
+ console.log('Activity responses:', {
+ commentsRes,
+ writeupsRes,
+ lessonsRes,
+ });
+ setRecentComments(commentsRes || []);
+ setRecentWriteups(writeupsRes || []);
+ setRecentLessons(lessonsRes || []);
+ } catch (error) {
+ console.error('Failed to fetch recent activity:', error);
+ setRecentComments([]);
+ setRecentWriteups([]);
+ setRecentLessons([]);
+ }
+ };
+
+ const fetchStats = async () => {
+ try {
+ console.log('Fetching platform stats...');
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/stats`,
+ 'GET'
+ );
+ console.log('Stats response:', response);
+ setStats(response);
+ } catch (error) {
+ console.error('Failed to fetch platform stats', error);
+ setStats(null);
+ }
+ };
+
+ // Autocomplete functions
+ const fetchUserSuggestions = async (query) => {
+ if (!query || query.length < 2) {
+ setUserSuggestions([]);
+ setShowUserSuggestions(false);
+ return;
+ }
+
+ try {
+ const response = await request(
+ `${
+ process.env.NEXT_PUBLIC_API_URL
+ }/admin/users?search=${encodeURIComponent(query)}&size=10`,
+ 'GET'
+ );
+
+ if (response && response.result) {
+ setUserSuggestions(response.result);
+ setShowUserSuggestions(true);
+ } else {
+ setUserSuggestions([]);
+ setShowUserSuggestions(false);
+ }
+ } catch (error) {
+ console.error('Failed to fetch user suggestions:', error);
+ setUserSuggestions([]);
+ setShowUserSuggestions(false);
+ }
+ };
+
+ const fetchChallengeSuggestions = async (query) => {
+ if (!query || query.length < 2) {
+ setChallengeSuggestions([]);
+ setShowChallengeSuggestions(false);
+ return;
+ }
+
+ try {
+ // Try to fetch both pending and approved challenges
+ const [pendingRes, approvedRes] = await Promise.all([
+ request(`${process.env.NEXT_PUBLIC_API_URL}/pending`, 'GET'),
+ request(
+ `${
+ process.env.NEXT_PUBLIC_API_URL
+ }/challenges?search=${encodeURIComponent(query)}&limit=10`,
+ 'GET'
+ ),
+ ]);
+
+ let suggestions = [];
+
+ // Add pending challenges
+ if (pendingRes && Array.isArray(pendingRes)) {
+ const filteredPending = pendingRes.filter(
+ (challenge) =>
+ challenge.title.toLowerCase().includes(query.toLowerCase()) ||
+ challenge.id.toLowerCase().includes(query.toLowerCase())
+ );
+ suggestions = [...suggestions, ...filteredPending];
+ }
+
+ // Add approved challenges
+ if (approvedRes && Array.isArray(approvedRes)) {
+ const filteredApproved = approvedRes.filter(
+ (challenge) =>
+ challenge.title.toLowerCase().includes(query.toLowerCase()) ||
+ challenge.id.toLowerCase().includes(query.toLowerCase())
+ );
+ suggestions = [...suggestions, ...filteredApproved];
+ }
+
+ // Remove duplicates and limit to 10
+ const uniqueSuggestions = suggestions
+ .filter(
+ (challenge, index, self) =>
+ index === self.findIndex((c) => c.id === challenge.id)
+ )
+ .slice(0, 10);
+
+ setChallengeSuggestions(uniqueSuggestions);
+ setShowChallengeSuggestions(uniqueSuggestions.length > 0);
+ } catch (error) {
+ console.error('Failed to fetch challenge suggestions:', error);
+ setChallengeSuggestions([]);
+ setShowChallengeSuggestions(false);
+ }
+ };
+
+ // Handle autocomplete selection
+ const handleUserSelection = (user) => {
+ setUserSearchQuery(user.username);
+ document.getElementById('usernameInput').value = user.username;
+ setShowUserSuggestions(false);
+ };
+
+ const handleChallengeSelection = (challenge) => {
+ setChallengeSearchQuery(challenge.id);
+ document.getElementById('challengeIdInput').value = challenge.id;
+ setShowChallengeSuggestions(false);
+ };
+
+ // Handle input changes
+ const handleUserInputChange = (e) => {
+ const value = e.target.value;
+ setUserSearchQuery(value);
+
+ if (value.length === 0) {
+ setUserSuggestions([]);
+ setShowUserSuggestions(false);
+ } else {
+ fetchUserSuggestions(value);
+ }
+ };
+
+ const handleChallengeInputChange = (e) => {
+ const value = e.target.value;
+ setChallengeSearchQuery(value);
+
+ if (value.length === 0) {
+ setChallengeSuggestions([]);
+ setShowChallengeSuggestions(false);
+ } else {
+ fetchChallengeSuggestions(value);
+ }
+ };
+
+ // Handle functions
const handleSelectChallenge = (id) => {
- setSelectedChallenges(prev => {
+ setSelectedChallenges((prev) => {
if (prev.includes(id)) {
- return prev.filter(item => item !== id);
+ return prev.filter((item) => item !== id);
} else {
return [...prev, id];
}
@@ -50,26 +363,30 @@ export default function Competitions() {
};
const resetFields = () => {
- document.getElementById('usernameInput').value = "";
- document.getElementById('reasonInput').value = "";
+ document.getElementById('usernameInput').value = '';
+ document.getElementById('reasonInput').value = '';
+ setUserSearchQuery('');
+ setShowUserSuggestions(false);
+ setUserSuggestions([]);
};
- const fetchPendingChallenges = async () => {
- try {
- const response = await request(process.env.NEXT_PUBLIC_API_URL + '/pending', "GET");
- console.log(response)
- setPendingChallenges(response);
- } catch (error) {
- console.error(error);
- }
+ const resetChallengeFields = () => {
+ document.getElementById('challengeIdInput').value = '';
+ document.getElementById('challengeReasonInput').value = '';
+ setChallengeSearchQuery('');
+ setShowChallengeSuggestions(false);
+ setChallengeSuggestions([]);
};
const handleApproveChallenge = async () => {
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/challenges/${selectedId}/approve`, "POST", { bonusPoints });
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/challenges/${selectedId}/approve`,
+ 'POST',
+ { bonusPoints }
+ );
console.log(response);
- // Handle success or error response
- fetchPendingChallenges(); // Refresh pending challenges
+ fetchPendingChallenges();
} catch (error) {
console.error(error);
}
@@ -79,138 +396,166 @@ export default function Competitions() {
const challengeId = document.getElementById('challengeIdInput').value;
const reason = document.getElementById('challengeReasonInput').value;
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${challengeId}/deleteChallenge`, "POST", {reason});
- if(response.success){
- alert("Challenge deleted successfully!");
- }else {
- alert("Failed to delete challenge.");
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${challengeId}/deleteChallenge`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('Challenge deleted successfully!', 'success');
+ } else {
+ showNotification('Failed to delete challenge.', 'error');
}
- document.getElementById('challengeIdInput').value = "";
- document.getElementById('challengeReasonInput').value = "";
-
-
- }catch(err){
+ resetChallengeFields();
+ } catch (err) {
console.log(err);
- alert("An error occurred while deleting the challenge.");
+ showNotification(
+ 'An error occurred while deleting the challenge.',
+ 'error'
+ );
}
-
};
const handleUnapproveChallenge = async () => {
const challengeId = document.getElementById('challengeIdInput').value;
const reason = document.getElementById('challengeReasonInput').value;
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${challengeId}/unapproveChallenge`, "POST", {reason});
- if(response.success){
- alert("Challenge unapproved successfully!");
- }else {
- alert("Failed to unapprove challenge.");
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${challengeId}/unapproveChallenge`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('Challenge unapproved successfully!', 'success');
+ } else {
+ showNotification('Failed to unapprove challenge.', 'error');
}
- document.getElementById('challengeIdInput').value = "";
- document.getElementById('challengeReasonInput').value = "";
-
-
- }catch(err){
+ resetChallengeFields();
+ } catch (err) {
console.log(err);
- alert("An error occurred while unapproving the challenge.");
+ showNotification(
+ 'An error occurred while unapproving the challenge.',
+ 'error'
+ );
}
-
};
const handleResyncLeaderboard = async () => {
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/syncLeaderboard`, "POST");
- if(response.success){
- alert("Leaderboard resynced successfully!");
- }else {
- alert("Failed to resync leaderboard.");
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/syncLeaderboard`,
+ 'POST'
+ );
+ if (response.success) {
+ showNotification('Leaderboard resynced successfully!', 'success');
+ } else {
+ showNotification('Failed to resync leaderboard.', 'error');
}
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while resyncing the leaderboard.");
+ showNotification(
+ 'An error occurred while resyncing the leaderboard.',
+ 'error'
+ );
}
};
- useEffect(() => {
- fetchPendingChallenges();
- }, []);
-
const handleResetPFP = async () => {
const username = document.getElementById('usernameInput').value;
const reason = document.getElementById('reasonInput').value;
- console.log('REASON: ', reason);
if (!username) {
- alert("Please enter a username.");
+ showNotification('Please enter a username.', 'warning');
return;
}
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetPFP`, "POST", { reason });
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetPFP`,
+ 'POST',
+ { reason }
+ );
if (response.success) {
- alert("Profile picture reset successfully!");
+ showNotification('Profile picture reset successfully!', 'success');
} else {
- alert("Failed to reset profile picture.");
+ showNotification('Failed to reset profile picture.', 'error');
}
-
resetFields();
-
} catch (error) {
console.error(error);
- alert("An error occurred while resetting the profile picture.");
+ showNotification(
+ 'An error occurred while resetting the profile picture.',
+ 'error'
+ );
}
};
const deleteBulk = async () => {
if (selectedChallenges.length === 0) {
- alert("No challenges selected.");
+ showNotification('No challenges selected.', 'warning');
return;
}
-
- if (!confirm("Are you sure you want to delete the selected challenges?")) {
+
+ if (!confirm('Are you sure you want to delete the selected challenges?')) {
return;
}
+
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/deleteChallenges`, "POST", { challengeIds: selectedChallenges });
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/deleteChallenges`,
+ 'POST',
+ { challengeIds: selectedChallenges }
+ );
if (response.success) {
- alert("Selected challenges deleted successfully!");
- setSelectedChallenges([]); // Clear selected challenges
- fetchPendingChallenges(); // Refresh pending challenges
+ showNotification(
+ 'Selected challenges deleted successfully!',
+ 'success'
+ );
+ setSelectedChallenges([]);
+ fetchPendingChallenges();
} else {
- alert("Failed to delete selected challenges.");
+ showNotification('Failed to delete selected challenges.', 'error');
}
} catch (error) {
console.error(error);
- alert("An error occurred while deleting the selected challenges.");
+ showNotification(
+ 'An error occurred while deleting the selected challenges.',
+ 'error'
+ );
}
};
-
const handleResetBanner = async () => {
const username = document.getElementById('usernameInput').value;
const reason = document.getElementById('reasonInput').value;
- if(!username) {
- alert("Please enter a username.");
+ if (!username) {
+ showNotification('Please enter a username.', 'warning');
return;
}
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetBanner`, "POST", {reason});
- if(response.success){
- alert("Banner reset successfully!");
- }else {
- alert("Failed to reset banner.");
- }
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetBanner`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('Banner reset successfully!', 'success');
+ } else {
+ showNotification('Failed to reset banner.', 'error');
+ }
resetFields();
-
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while resetting the banner.");
+ showNotification(
+ 'An error occurred while resetting the banner.',
+ 'error'
+ );
}
};
@@ -219,46 +564,55 @@ export default function Competitions() {
const reason = document.getElementById('reasonInput').value;
if (!username) {
- alert("Please enter a username.");
+ showNotification('Please enter a username.', 'warning');
return;
}
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/disableAccount`, "POST", { reason });
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/disableAccount`,
+ 'POST',
+ { reason }
+ );
if (response.success) {
- alert("Account disabled successfully!");
+ showNotification('Account disabled successfully!', 'success');
} else {
- alert("Failed to disable account.");
+ showNotification('Failed to disable account.', 'error');
}
-
resetFields();
-
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while disabling the account.");
+ showNotification(
+ 'An error occurred while disabling the account.',
+ 'error'
+ );
}
};
- const handleResetBio = async () => {
+ const handleResetBio = async () => {
const username = document.getElementById('usernameInput').value;
const reason = document.getElementById('reasonInput').value;
if (!username) {
- alert("Please enter a username.");
+ showNotification('Please enter a username.', 'warning');
return;
}
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetBio`, "POST", {reason});
- if(response.success){
- alert("Bio reset successfully!");
- }else{
- alert("Failed to reset bio.");
- }
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/resetBio`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('Bio reset successfully!', 'success');
+ } else {
+ showNotification('Failed to reset bio.', 'error');
+ }
resetFields();
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while resetting the bio.");
+ showNotification('An error occurred while resetting the bio.', 'error');
}
};
@@ -267,21 +621,28 @@ export default function Competitions() {
const reason = document.getElementById('reasonInput').value;
if (!username) {
- alert("Please enter a username.");
+ showNotification('Please enter a username.', 'warning');
return;
}
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/enableAccount`, "POST", {reason});
- if(response.success){
- alert("Account enabled successfully!");
- }else {
- alert("Failed to enable account.");
- }
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/enableAccount`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('Account enabled successfully!', 'success');
+ } else {
+ showNotification('Failed to enable account.', 'error');
+ }
resetFields();
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while enabling the account.");
+ showNotification(
+ 'An error occurred while enabling the account.',
+ 'error'
+ );
}
};
@@ -290,233 +651,958 @@ export default function Competitions() {
const reason = document.getElementById('reasonInput').value;
if (!username) {
- alert("Please enter a username.");
+ showNotification('Please enter a username.', 'warning');
return;
}
- try{
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/warnUser`, "POST", {reason});
- if(response.success){
- alert("User warned successfully!");
- }else {
- alert("Failed to warn user.");
- }
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/admin/${username}/warnUser`,
+ 'POST',
+ { reason }
+ );
+ if (response.success) {
+ showNotification('User warned successfully!', 'success');
+ } else {
+ showNotification('Failed to warn user.', 'error');
+ }
resetFields();
- }catch(err){
+ } catch (err) {
console.log(err);
- alert("An error occurred while warning the user.");
+ showNotification('An error occurred while warning the user.', 'error');
}
};
- // Fetch platform stats
- const [stats, setStats] = useState(null);
+ // User pagination handlers
+ const handleNextUserPage = () => {
+ if (currentUserPage < totalUserPages - 1) {
+ fetchUsers(currentUserPage + 1);
+ }
+ };
+
+ const handlePrevUserPage = () => {
+ if (currentUserPage > 0) {
+ fetchUsers(currentUserPage - 1);
+ }
+ };
+ // Initial data fetch
useEffect(() => {
- const fetchStats = async () => {
+ console.log('=== MODERATION PANEL INITIALIZING ===');
+ console.log('API URL:', process.env.NEXT_PUBLIC_API_URL);
+ console.log('Starting data fetch sequence...');
+
+ const fetchAllData = async () => {
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/admin/stats`, "GET");
- setStats(response);
+ console.log('1. Fetching reports...');
+ await fetchReports();
+
+ console.log('2. Fetching pending challenges...');
+ await fetchPendingChallenges();
+
+ console.log('3. Fetching users...');
+ await fetchUsers();
+
+ console.log('4. Fetching recent activity...');
+ await fetchRecentActivity();
+
+ console.log('5. Fetching stats...');
+ await fetchStats();
+
+ console.log('=== ALL DATA FETCH COMPLETE ===');
} catch (error) {
- console.error("Failed to fetch platform stats", error);
+ console.error('Error in data fetch sequence:', error);
}
};
- fetchStats();
+
+ fetchAllData();
}, []);
+ // Handle clicking outside autocomplete dropdowns
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ const userInput = document.getElementById('usernameInput');
+ const challengeInput = document.getElementById('challengeIdInput');
+
+ if (
+ userInput &&
+ !userInput.contains(event.target) &&
+ !event.target.closest('.user-suggestions')
+ ) {
+ setShowUserSuggestions(false);
+ }
+
+ if (
+ challengeInput &&
+ !challengeInput.contains(event.target) &&
+ !event.target.closest('.challenge-suggestions')
+ ) {
+ setShowChallengeSuggestions(false);
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, []);
+
+ // Tab navigation component
+ const TabButton = ({ id, label, icon: Icon, count }) => (
+
setActiveTab(id)}
+ className={`flex items-center rounded-lg px-4 py-2 font-medium transition-all duration-200 ${
+ activeTab === id
+ ? 'bg-blue-600 text-white shadow-lg'
+ : 'bg-neutral-800 text-gray-300 hover:bg-neutral-700 hover:text-white'
+ }`}
+ >
+
+ {label}
+ {count !== undefined && (
+
+ {count}
+
+ )}
+
+ );
+
return (
<>
CTFGuide Moderation Panel
-
+
-
+
-
-
-
+
+
+ {/* Header */}
+
-
ADMIN CENTER
-
ΥΠΕΡΑΣΠΙΣΗ ΤΟΥ CTFGUIDE ΑΠΟ ΤΟ OPS
+
+ Admin Center
+
+
+ ΥΠΕΡΑΣΠΙΣΗ ΤΟΥ CTFGUIDE ΑΠΟ ΤΟ OPS
+
-
-
-
Quick Approve
-
Quick Deny
+
+
-
-
-
-
-
-
-
-
-
USER ACTIONS
-
-
-
-
- Disable Account
-
-
- Enable Account
-
-
- Warn User
-
-
- Reset PFP
-
-
- Reset Banner
-
-
- Reset Bio
-
+
-
-
-
-
-
-
-
CHALLENGE ACTIONS
-
-
- Delete Challenge
- Unapprove Challenge
- Resync Leaderboard
-
-
-
-
-
Challenges Pending Approval
- {selectedChallenges.length > 0 &&
Delete Selected}
-
- {pendingChallenges && pendingChallenges.length > 0 ? (
- pendingChallenges.map((challenge) => (
-
{setSelectedId(challenge.id); setChallengeIsOpen(true);}} className='bg-neutral-800 w-full mb-2 border focus:bg-blue-900 focus:border-blue-500 border-neutral-700 hover:bg-neutral-700/50 cursor-pointer px-2 py-1 flex items-center text-sm'>
+ {/* Tab Navigation */}
+
+
+
+
+
+
+
+
+ {/* Tab Content */}
+ {activeTab === 'overview' && (
+
+ {/* Platform Stats */}
+
+
+ Platform Statistics
+
+ {stats ? (
+
+
+
+ {stats.userCount}
+
+
Total Users
+
+
+
+ {stats.challengeCount}
+
+
Total Challenges
+
+
+
+ {stats.verifiedChallengeCount}
+
+
Verified Challenges
+
+
+ ) : (
+
+
Failed to load statistics
+
+ )}
+
+ {/* Recent Sign-Ups Section */}
+ {stats &&
+ stats.recentSignUps &&
+ stats.recentSignUps.length > 0 && (
+
+
+
+ Recent Sign-Ups
+
+
+
+ {stats.recentSignUpsCount24h || 0} users joined in
+ last 24h
+
+
+ Showing latest{' '}
+ {Math.min(6, stats.recentSignUps.length)} users
+
+
+
+
+ {stats.recentSignUps.slice(0, 6).map((user) => (
+
+ window.open(`/users/${user.username}`, '_blank')
+ }
+ >
+
+
+
+
+ {user.username}
+
+
+ {new Date(
+ user.createdAt
+ ).toLocaleDateString()}
+
+
+
+
+ ))}
+
+
+ )}
+
+
+ {/* Quick Actions */}
+
+ {/* User Actions */}
+
+
+
+
+
+
User Management
+
+
+
+
+
+
+
e.stopPropagation()} // Prevent click event propagation
- type="checkbox"
- checked={selectedChallenges.includes(challenge.id)}
- onChange={() => handleSelectChallenge(challenge.id)}
- className=""
+ type="text"
+ placeholder="Enter username to manage"
+ className="w-full rounded-xl border-0 bg-neutral-700/80 py-3 pl-12 pr-4 text-white placeholder-gray-400 shadow-inner transition-all duration-200 focus:bg-neutral-700 focus:ring-2 focus:ring-blue-500/50 focus:ring-offset-0"
+ id="usernameInput"
+ value={userSearchQuery}
+ onChange={handleUserInputChange}
+ onFocus={() => {
+ if (userSuggestions.length > 0) {
+ setShowUserSuggestions(true);
+ }
+ }}
+ onBlur={() => {
+ // Delay hiding suggestions to allow clicking
+ setTimeout(
+ () => setShowUserSuggestions(false),
+ 200
+ );
+ }}
+ autoComplete="off"
/>
-
-
{challenge.title}
-
-
-
Submitted by {challenge.creator}
-
{new Date(challenge.createdAt).toLocaleString([], { hour: 'numeric', minute: 'numeric', hour12: true, month: 'short', day: 'numeric' })}
+
+ {/* User Suggestions Dropdown */}
+ {showUserSuggestions && userSuggestions.length > 0 && (
+
+ {userSuggestions.map((user) => (
+
handleUserSelection(user)}
+ >
+
+
+
+ {user.username}
+
+
+ {user.points || 0} points • Joined{' '}
+ {new Date(
+ user.createdAt
+ ).toLocaleDateString()}
+
+
+ {user.disabled && (
+
+ Disabled
+
+ )}
+
+ ))}
+
+ )}
+
+
+
+
+
+
+
+
+ Disable Account
+
+
+
+
+ Enable Account
+
+
+
+
+
+
+ Warn User
+
+
+
+
+ Reset Avatar
+
+
+
+
+
+
+ Reset Banner
+
+
+
+
+ Reset Bio
+
+
+
+
+
+
+ {/* Challenge Actions */}
+
+
+
+
+
+
+ Challenge Management
+
+
+
+
+
+
+
+
+
{
+ if (challengeSuggestions.length > 0) {
+ setShowChallengeSuggestions(true);
+ }
+ }}
+ onBlur={() => {
+ // Delay hiding suggestions to allow clicking
+ setTimeout(
+ () => setShowChallengeSuggestions(false),
+ 200
+ );
+ }}
+ autoComplete="off"
+ />
+
+ {/* Challenge Suggestions Dropdown */}
+ {showChallengeSuggestions &&
+ challengeSuggestions.length > 0 && (
+
+ {challengeSuggestions.map((challenge) => (
+
+ handleChallengeSelection(challenge)
+ }
+ >
+
+
+
+ {challenge.title}
+
+
+ ID: {challenge.id}
+
+
+ Created by{' '}
+ {challenge.creator ||
+ challenge.author ||
+ 'Unknown'}{' '}
+ •{' '}
+ {new Date(
+ challenge.createdAt
+ ).toLocaleDateString()}
+
+
+
+ {challenge.verified ? (
+
+ Approved
+
+ ) : (
+
+ Pending
+
+ )}
+ {challenge.difficulty && (
+
+ {challenge.difficulty}
+
+ )}
+
+
+
+ ))}
+
+ )}
+
+
+
+
+
+
+
+ Delete Challenge
+
+ Permanent
+
+
+
+
+
+ Unapprove Challenge
+
+ Reversible
+
+
+
+
+
+ Resync Leaderboard
+
+ System
+
+
+
+
+
+
+
+ )}
+
+ {activeTab === 'users' && (
+
+
+
+ User Management
+
+
+
+ Page {currentUserPage + 1} of {totalUserPages || 1} (
+ {totalUsers} total users)
+
+
+
+
+
+ = totalUserPages - 1}
+ className="rounded-lg bg-neutral-700 p-2 text-white transition-colors duration-200 hover:bg-neutral-600 disabled:cursor-not-allowed disabled:opacity-50"
+ >
+
+
+
+
+
+
+
+ {users && users.length > 0 ? (
+ users.map((user) => (
+
+ window.open(`/users/${user.username}`, '_blank')
+ }
+ >
+
+
+
+
+ {user.username}
+
+
+ {user.points || 0} points
+
+
+ {new Date(user.createdAt).toLocaleDateString()}
+
+
))
) : (
-
Nothing to show
+
+
+ {totalUsers === 0
+ ? 'Loading users...'
+ : 'No users found'}
+
+
)}
-
-
Submitted Reports
-
-
- {reports && reports.length > 0 ? (
- reports.map((report) => (
-
{
- setSelectedReport(report);
- setReportIsOpen(true);
- }}
+ )}
+
+ {activeTab === 'challenges' && (
+
+
+
+ Pending Challenges
+
+ {selectedChallenges.length > 0 && (
+
-
-
- {report.type} REPORT
- {report.metadata?.severity && (
-
- {report.metadata.severity}
-
- )}
-
-
-
-
Reported by {report.userId}
-
{new Date(report.createdAt).toLocaleString([], { hour: 'numeric', minute: 'numeric', hour12: true, month: 'short', day: 'numeric' })}
+
Delete Selected (
+ {selectedChallenges.length})
+
+ )}
+
+
+
+ {pendingChallenges && pendingChallenges.length > 0 ? (
+ pendingChallenges.map((challenge) => (
+
{
+ setSelectedId(challenge.id);
+ setChallengeIsOpen(true);
+ }}
+ className="cursor-pointer rounded-lg bg-neutral-700 p-4 transition-colors duration-200 hover:bg-neutral-600"
+ >
+
+
e.stopPropagation()}
+ type="checkbox"
+ checked={selectedChallenges.includes(challenge.id)}
+ onChange={() => handleSelectChallenge(challenge.id)}
+ className="h-4 w-4 rounded border-neutral-500 bg-neutral-600 text-blue-600 focus:ring-blue-500"
+ />
+
+
+ {challenge.title}
+
+
+ Submitted by{' '}
+
+ {challenge.creator}
+
+
+
+
+
+ {new Date(challenge.createdAt).toLocaleString(
+ [],
+ {
+ hour: 'numeric',
+ minute: 'numeric',
+ hour12: true,
+ month: 'short',
+ day: 'numeric',
+ }
+ )}
+
+
+
+ ))
+ ) : (
+
- ))
- ) : (
-
No reports to show
- )}
-
+ )}
+
-
+ )}
-
-
Platform Stats
- {stats ? (
-
-
-
-
{stats.userCount}
-
Total Users
-
-
-
{stats.challengeCount}
-
Total Challenges
-
-
-
{stats.verifiedChallengeCount}
-
Verified Challenges
-
-
-
-
-
Recent Sign-Ups
-
- {stats.recentSignUps.map((user) => (
-
window.open(`/users/${user.username}`, '_blank')}>
-
-
-
{user.username}
-
{new Date(user.createdAt).toLocaleString()}
+ {activeTab === 'reports' && (
+
+
+ Submitted Reports
+
+
+ {reports && reports.length > 0 ? (
+ reports.map((report) => {
+ let metadata = {};
+ try {
+ metadata = JSON.parse(report.metadata || '{}');
+ } catch (e) {
+ console.error('Failed to parse report metadata:', e);
+ }
+
+ return (
+
{
+ setSelectedReport(report);
+ setReportIsOpen(true);
+ }}
+ >
+
+
+
+ {report.type} REPORT
+ {metadata.severity && (
+
+ {metadata.severity}
+
+ )}
+
+
+ {report.desc && report.desc.length > 100
+ ? `${report.desc.substring(0, 100)}...`
+ : report.desc}
+
+
+
+
+ Reported by{' '}
+
+ {report.userId}
+
+
+
+ {new Date(report.createdAt).toLocaleString([], {
+ hour: 'numeric',
+ minute: 'numeric',
+ hour12: true,
+ month: 'short',
+ day: 'numeric',
+ })}
+
+
- ))}
+ );
+ })
+ ) : (
+
-
- ) : (
-
Failed to load stats
- )}
-
-
Selected Content ID's
-
+ )}
+
+
+ )}
+ {activeTab === 'activity' && (
+
+ {/* Recent Comments */}
+
+
+ Recent Comments
+
+
+ {recentComments && recentComments.length > 0 ? (
+ recentComments.map((comment) => (
+
+
+
+
+ {comment.content}
+
+
+ by{' '}
+
+ {comment.user?.username || 'Unknown'}
+
+ {comment.challenge && (
+
+ {' '}
+ on{' '}
+
+ {comment.challenge.title}
+
+
+ )}
+
+
+
+ {new Date(comment.createdAt).toLocaleString()}
+
+
+
+ ))
+ ) : (
+
+ No recent comments
+
+ )}
+
+
+ {/* Recent Writeups */}
+
+
+ Recent Writeups
+
+
+ {recentWriteups && recentWriteups.length > 0 ? (
+ recentWriteups.map((writeup) => (
+
+
+
+
+ {writeup.title}
+
+
+ by{' '}
+
+ {writeup.user?.username || 'Unknown'}
+
+ {writeup.challenge && (
+
+ {' '}
+ for{' '}
+
+ {writeup.challenge.title}
+
+
+ )}
+
+
+
+ {new Date(writeup.createdAt).toLocaleString()}
+
+
+
+ ))
+ ) : (
+
+ No recent writeups
+
+ )}
+
+
+ {/* Recent Lessons */}
+
+
+ Recent Lessons
+
+
+ {recentLessons && recentLessons.length > 0 ? (
+ recentLessons.map((lesson) => (
+
+
+
+
+ {lesson.title}
+
+
+ {lesson.description}
+
+
+ by{' '}
+
+ {lesson.author || 'Unknown'}
+
+
+
+
+ {new Date(lesson.createdAt).toLocaleString()}
+
+
+
+ ))
+ ) : (
+
+ No recent lessons
+
+ )}
+
+
+
+ )}
-
-
-
+
+
+
+
+ {/* Notification Modal */}
+
>
);
-}
\ No newline at end of file
+}
diff --git a/yarn.lock b/yarn.lock
index afc2d4f6..654382c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -43,7 +43,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz"
integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==
-"@babel/core@^7.11.1", "@babel/core@^7.22.9":
+"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.22.9", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0":
version "7.26.10"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz"
integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==
@@ -1128,7 +1128,7 @@
"@codemirror/view" "^6.0.0"
"@lezer/highlight" "^1.0.0"
-"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.6.0":
+"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.6.0", "@codemirror/view@>=6.0.0":
version "6.36.5"
resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.36.5.tgz"
integrity sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg==
@@ -1170,7 +1170,7 @@
resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz"
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
-"@emotion/is-prop-valid@^1.2.1", "@emotion/is-prop-valid@1.2.2":
+"@emotion/is-prop-valid@*", "@emotion/is-prop-valid@^1.2.1", "@emotion/is-prop-valid@1.2.2":
version "1.2.2"
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz"
integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
@@ -1187,7 +1187,7 @@
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
-"@emotion/react@^11.13.3":
+"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.13.3", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
@@ -1217,7 +1217,7 @@
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
-"@emotion/styled@^11.11.0":
+"@emotion/styled@^11.11.0", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1":
version "11.11.0"
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz"
integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==
@@ -1269,6 +1269,397 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
+"@firebase/ai@1.4.1":
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/@firebase/ai/-/ai-1.4.1.tgz"
+ integrity sha512-bcusQfA/tHjUjBTnMx6jdoPMpDl3r8K15Z+snHz9wq0Foox0F/V+kNLXucEOHoTL2hTc9l+onZCyBJs2QoIC3g==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.3"
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/analytics-compat@0.2.23":
+ version "0.2.23"
+ resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.23.tgz"
+ integrity sha512-3AdO10RN18G5AzREPoFgYhW6vWXr3u+OYQv6pl3CX6Fky8QRk0AHurZlY3Q1xkXO0TDxIsdhO3y65HF7PBOJDw==
+ dependencies:
+ "@firebase/analytics" "0.10.17"
+ "@firebase/analytics-types" "0.8.3"
+ "@firebase/component" "0.6.18"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/analytics-types@0.8.3":
+ version "0.8.3"
+ resolved "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz"
+ integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==
+
+"@firebase/analytics@0.10.17":
+ version "0.10.17"
+ resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.17.tgz"
+ integrity sha512-n5vfBbvzduMou/2cqsnKrIes4auaBjdhg8QNA2ZQZ59QgtO2QiwBaXQZQE4O4sgB0Ds1tvLgUUkY+pwzu6/xEg==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/installations" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/app-check-compat@0.3.26":
+ version "0.3.26"
+ resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.26.tgz"
+ integrity sha512-PkX+XJMLDea6nmnopzFKlr+s2LMQGqdyT2DHdbx1v1dPSqOol2YzgpgymmhC67vitXVpNvS3m/AiWQWWhhRRPQ==
+ dependencies:
+ "@firebase/app-check" "0.10.1"
+ "@firebase/app-check-types" "0.5.3"
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/app-check-interop-types@0.3.3":
+ version "0.3.3"
+ resolved "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz"
+ integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==
+
+"@firebase/app-check-types@0.5.3":
+ version "0.5.3"
+ resolved "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz"
+ integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==
+
+"@firebase/app-check@0.10.1":
+ version "0.10.1"
+ resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.10.1.tgz"
+ integrity sha512-MgNdlms9Qb0oSny87pwpjKush9qUwCJhfmTJHDfrcKo4neLGiSeVE4qJkzP7EQTIUFKp84pbTxobSAXkiuQVYQ==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/app-compat@0.4.2", "@firebase/app-compat@0.x":
+ version "0.4.2"
+ resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.4.2.tgz"
+ integrity sha512-LssbyKHlwLeiV8GBATyOyjmHcMpX/tFjzRUCS1jnwGAew1VsBB4fJowyS5Ud5LdFbYpJeS+IQoC+RQxpK7eH3Q==
+ dependencies:
+ "@firebase/app" "0.13.2"
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/app-types@0.9.3", "@firebase/app-types@0.x":
+ version "0.9.3"
+ resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz"
+ integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==
+
+"@firebase/app@0.13.2", "@firebase/app@0.x":
+ version "0.13.2"
+ resolved "https://registry.npmjs.org/@firebase/app/-/app-0.13.2.tgz"
+ integrity sha512-jwtMmJa1BXXDCiDx1vC6SFN/+HfYG53UkfJa6qeN5ogvOunzbFDO3wISZy5n9xgYFUrEP6M7e8EG++riHNTv9w==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/auth-compat@0.5.28":
+ version "0.5.28"
+ resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.28.tgz"
+ integrity sha512-HpMSo/cc6Y8IX7bkRIaPPqT//Jt83iWy5rmDWeThXQCAImstkdNo3giFLORJwrZw2ptiGkOij64EH1ztNJzc7Q==
+ dependencies:
+ "@firebase/auth" "1.10.8"
+ "@firebase/auth-types" "0.13.0"
+ "@firebase/component" "0.6.18"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/auth-interop-types@0.2.4":
+ version "0.2.4"
+ resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz"
+ integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==
+
+"@firebase/auth-types@0.13.0":
+ version "0.13.0"
+ resolved "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz"
+ integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==
+
+"@firebase/auth@1.10.8":
+ version "1.10.8"
+ resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.10.8.tgz"
+ integrity sha512-GpuTz5ap8zumr/ocnPY57ZanX02COsXloY6Y/2LYPAuXYiaJRf6BAGDEdRq1BMjP93kqQnKNuKZUTMZbQ8MNYA==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/component@0.6.18":
+ version "0.6.18"
+ resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.18.tgz"
+ integrity sha512-n28kPCkE2dL2U28fSxZJjzPPVpKsQminJ6NrzcKXAI0E/lYC8YhfwpyllScqVEvAI3J2QgJZWYgrX+1qGI+SQQ==
+ dependencies:
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/data-connect@0.3.10":
+ version "0.3.10"
+ resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.10.tgz"
+ integrity sha512-VMVk7zxIkgwlVQIWHOKFahmleIjiVFwFOjmakXPd/LDgaB/5vzwsB5DWIYo+3KhGxWpidQlR8geCIn39YflJIQ==
+ dependencies:
+ "@firebase/auth-interop-types" "0.2.4"
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/database-compat@2.0.11":
+ version "2.0.11"
+ resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.11.tgz"
+ integrity sha512-itEsHARSsYS95+udF/TtIzNeQ0Uhx4uIna0sk4E0wQJBUnLc/G1X6D7oRljoOuwwCezRLGvWBRyNrugv/esOEw==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/database" "1.0.20"
+ "@firebase/database-types" "1.0.15"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/database-types@1.0.15":
+ version "1.0.15"
+ resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.15.tgz"
+ integrity sha512-XWHJ0VUJ0k2E9HDMlKxlgy/ZuTa9EvHCGLjaKSUvrQnwhgZuRU5N3yX6SZ+ftf2hTzZmfRkv+b3QRvGg40bKNw==
+ dependencies:
+ "@firebase/app-types" "0.9.3"
+ "@firebase/util" "1.12.1"
+
+"@firebase/database@1.0.20":
+ version "1.0.20"
+ resolved "https://registry.npmjs.org/@firebase/database/-/database-1.0.20.tgz"
+ integrity sha512-H9Rpj1pQ1yc9+4HQOotFGLxqAXwOzCHsRSRjcQFNOr8lhUt6LeYjf0NSRL04sc4X0dWe8DsCvYKxMYvFG/iOJw==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.3"
+ "@firebase/auth-interop-types" "0.2.4"
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ faye-websocket "0.11.4"
+ tslib "^2.1.0"
+
+"@firebase/firestore-compat@0.3.53":
+ version "0.3.53"
+ resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.53.tgz"
+ integrity sha512-qI3yZL8ljwAYWrTousWYbemay2YZa+udLWugjdjju2KODWtLG94DfO4NALJgPLv8CVGcDHNFXoyQexdRA0Cz8Q==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/firestore" "4.8.0"
+ "@firebase/firestore-types" "3.0.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/firestore-types@3.0.3":
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz"
+ integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==
+
+"@firebase/firestore@4.8.0":
+ version "4.8.0"
+ resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.8.0.tgz"
+ integrity sha512-QSRk+Q1/CaabKyqn3C32KSFiOdZpSqI9rpLK5BHPcooElumOBooPFa6YkDdiT+/KhJtel36LdAacha9BptMj2A==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ "@firebase/webchannel-wrapper" "1.0.3"
+ "@grpc/grpc-js" "~1.9.0"
+ "@grpc/proto-loader" "^0.7.8"
+ tslib "^2.1.0"
+
+"@firebase/functions-compat@0.3.26":
+ version "0.3.26"
+ resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.26.tgz"
+ integrity sha512-A798/6ff5LcG2LTWqaGazbFYnjBW8zc65YfID/en83ALmkhu2b0G8ykvQnLtakbV9ajrMYPn7Yc/XcYsZIUsjA==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/functions" "0.12.9"
+ "@firebase/functions-types" "0.6.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/functions-types@0.6.3":
+ version "0.6.3"
+ resolved "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz"
+ integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==
+
+"@firebase/functions@0.12.9":
+ version "0.12.9"
+ resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.9.tgz"
+ integrity sha512-FG95w6vjbUXN84Ehezc2SDjGmGq225UYbHrb/ptkRT7OTuCiQRErOQuyt1jI1tvcDekdNog+anIObihNFz79Lg==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.3"
+ "@firebase/auth-interop-types" "0.2.4"
+ "@firebase/component" "0.6.18"
+ "@firebase/messaging-interop-types" "0.2.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/installations-compat@0.2.18":
+ version "0.2.18"
+ resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.18.tgz"
+ integrity sha512-aLFohRpJO5kKBL/XYL4tN+GdwEB/Q6Vo9eZOM/6Kic7asSUgmSfGPpGUZO1OAaSRGwF4Lqnvi1f/f9VZnKzChw==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/installations" "0.6.18"
+ "@firebase/installations-types" "0.5.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/installations-types@0.5.3":
+ version "0.5.3"
+ resolved "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz"
+ integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==
+
+"@firebase/installations@0.6.18":
+ version "0.6.18"
+ resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.18.tgz"
+ integrity sha512-NQ86uGAcvO8nBRwVltRL9QQ4Reidc/3whdAasgeWCPIcrhOKDuNpAALa6eCVryLnK14ua2DqekCOX5uC9XbU/A==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/util" "1.12.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/logger@0.4.4":
+ version "0.4.4"
+ resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz"
+ integrity sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==
+ dependencies:
+ tslib "^2.1.0"
+
+"@firebase/messaging-compat@0.2.22":
+ version "0.2.22"
+ resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.22.tgz"
+ integrity sha512-5ZHtRnj6YO6f/QPa/KU6gryjmX4Kg33Kn4gRpNU6M1K47Gm8kcQwPkX7erRUYEH1mIWptfvjvXMHWoZaWjkU7A==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/messaging" "0.12.22"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/messaging-interop-types@0.2.3":
+ version "0.2.3"
+ resolved "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz"
+ integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==
+
+"@firebase/messaging@0.12.22":
+ version "0.12.22"
+ resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.22.tgz"
+ integrity sha512-GJcrPLc+Hu7nk+XQ70Okt3M1u1eRr2ZvpMbzbc54oTPJZySHcX9ccZGVFcsZbSZ6o1uqumm8Oc7OFkD3Rn1/og==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/installations" "0.6.18"
+ "@firebase/messaging-interop-types" "0.2.3"
+ "@firebase/util" "1.12.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/performance-compat@0.2.20":
+ version "0.2.20"
+ resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.20.tgz"
+ integrity sha512-XkFK5NmOKCBuqOKWeRgBUFZZGz9SzdTZp4OqeUg+5nyjapTiZ4XoiiUL8z7mB2q+63rPmBl7msv682J3rcDXIQ==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/performance" "0.7.7"
+ "@firebase/performance-types" "0.2.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/performance-types@0.2.3":
+ version "0.2.3"
+ resolved "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz"
+ integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==
+
+"@firebase/performance@0.7.7":
+ version "0.7.7"
+ resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.7.tgz"
+ integrity sha512-JTlTQNZKAd4+Q5sodpw6CN+6NmwbY72av3Lb6wUKTsL7rb3cuBIhQSrslWbVz0SwK3x0ZNcqX24qtRbwKiv+6w==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/installations" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+ web-vitals "^4.2.4"
+
+"@firebase/remote-config-compat@0.2.18":
+ version "0.2.18"
+ resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.18.tgz"
+ integrity sha512-YiETpldhDy7zUrnS8e+3l7cNs0sL7+tVAxvVYU0lu7O+qLHbmdtAxmgY+wJqWdW2c9nDvBFec7QiF58pEUu0qQ==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/remote-config" "0.6.5"
+ "@firebase/remote-config-types" "0.4.0"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/remote-config-types@0.4.0":
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz"
+ integrity sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==
+
+"@firebase/remote-config@0.6.5":
+ version "0.6.5"
+ resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.6.5.tgz"
+ integrity sha512-fU0c8HY0vrVHwC+zQ/fpXSqHyDMuuuglV94VF6Yonhz8Fg2J+KOowPGANM0SZkLvVOYpTeWp3ZmM+F6NjwWLnw==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/installations" "0.6.18"
+ "@firebase/logger" "0.4.4"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/storage-compat@0.3.24":
+ version "0.3.24"
+ resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.24.tgz"
+ integrity sha512-XHn2tLniiP7BFKJaPZ0P8YQXKiVJX+bMyE2j2YWjYfaddqiJnROJYqSomwW6L3Y+gZAga35ONXUJQju6MB6SOQ==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/storage" "0.13.14"
+ "@firebase/storage-types" "0.8.3"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/storage-types@0.8.3":
+ version "0.8.3"
+ resolved "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz"
+ integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==
+
+"@firebase/storage@0.13.14":
+ version "0.13.14"
+ resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.14.tgz"
+ integrity sha512-xTq5ixxORzx+bfqCpsh+o3fxOsGoDjC1nO0Mq2+KsOcny3l7beyBhP/y1u5T6mgsFQwI1j6oAkbT5cWdDBx87g==
+ dependencies:
+ "@firebase/component" "0.6.18"
+ "@firebase/util" "1.12.1"
+ tslib "^2.1.0"
+
+"@firebase/util@1.12.1", "@firebase/util@1.x":
+ version "1.12.1"
+ resolved "https://registry.npmjs.org/@firebase/util/-/util-1.12.1.tgz"
+ integrity sha512-zGlBn/9Dnya5ta9bX/fgEoNC3Cp8s6h+uYPYaDieZsFOAdHP/ExzQ/eaDgxD3GOROdPkLKpvKY0iIzr9adle0w==
+ dependencies:
+ tslib "^2.1.0"
+
+"@firebase/webchannel-wrapper@1.0.3":
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz"
+ integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==
+
"@floating-ui/core@^1.6.0":
version "1.6.9"
resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz"
@@ -1301,7 +1692,7 @@
resolved "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz"
integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==
-"@fortawesome/fontawesome-svg-core@^6.3.0":
+"@fortawesome/fontawesome-svg-core@^6.3.0", "@fortawesome/fontawesome-svg-core@~1 || ~6":
version "6.4.0"
resolved "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz"
integrity sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==
@@ -1339,6 +1730,24 @@
resolved "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz"
integrity sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==
+"@grpc/grpc-js@~1.9.0":
+ version "1.9.15"
+ resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz"
+ integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==
+ dependencies:
+ "@grpc/proto-loader" "^0.7.8"
+ "@types/node" ">=12.12.47"
+
+"@grpc/proto-loader@^0.7.8":
+ version "0.7.15"
+ resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz"
+ integrity sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==
+ dependencies:
+ lodash.camelcase "^4.3.0"
+ long "^5.0.0"
+ protobufjs "^7.2.5"
+ yargs "^17.7.2"
+
"@headlessui/react@^1.7.2":
version "1.7.15"
resolved "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz"
@@ -1596,7 +2005,7 @@
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz"
integrity sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==
-"@mui/material@^5.0.0", "@mui/material@^5.15.2":
+"@mui/material@^5.0.0", "@mui/material@^5.15.2", "@mui/material@^5.4.1":
version "5.17.1"
resolved "https://registry.npmjs.org/@mui/material/-/material-5.17.1.tgz"
integrity sha512-2B33kQf+GmPnrvXXweWAx+crbiUEsxCdCN979QDYnlH9ox4pd+0/IBriWLV+l6ORoBF60w39cWjFnJYGFdzXcw==
@@ -1633,7 +2042,7 @@
csstype "^3.1.3"
prop-types "^15.8.1"
-"@mui/system@^5.17.1":
+"@mui/system@^5.17.1", "@mui/system@^5.4.1":
version "5.17.1"
resolved "https://registry.npmjs.org/@mui/system/-/system-5.17.1.tgz"
integrity sha512-aJrmGfQpyF0U4D4xYwA6ueVtQcEMebET43CUmKMP7e7iFh3sMIF3sBR0l8Urb4pqx1CBjHAaWgB0ojpND4Q3Jg==
@@ -1734,6 +2143,59 @@
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz"
+ integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
+
+"@protobufjs/base64@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz"
+ integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
+
+"@protobufjs/codegen@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz"
+ integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
+
+"@protobufjs/eventemitter@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz"
+ integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
+
+"@protobufjs/fetch@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz"
+ integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
+ dependencies:
+ "@protobufjs/aspromise" "^1.1.1"
+ "@protobufjs/inquire" "^1.1.0"
+
+"@protobufjs/float@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz"
+ integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
+
+"@protobufjs/inquire@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz"
+ integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
+
+"@protobufjs/path@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz"
+ integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
+
+"@protobufjs/pool@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz"
+ integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
+
+"@protobufjs/utf8@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz"
+ integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
+
"@puppeteer/browsers@2.3.0":
version "2.3.0"
resolved "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz"
@@ -2024,6 +2486,22 @@
dependencies:
"@types/ms" "*"
+"@types/eslint-scope@^3.7.7":
+ version "3.7.7"
+ resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz"
+ integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==
+ dependencies:
+ "@types/eslint" "*"
+ "@types/estree" "*"
+
+"@types/eslint@*":
+ version "9.6.1"
+ resolved "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz"
+ integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
"@types/estree-jsx@^1.0.0":
version "1.0.5"
resolved "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz"
@@ -2031,10 +2509,10 @@
dependencies:
"@types/estree" "*"
-"@types/estree@*", "@types/estree@^1.0.0":
- version "1.0.7"
- resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz"
- integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
+"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.8":
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz"
+ integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
"@types/estree@0.0.39":
version "0.0.39"
@@ -2068,7 +2546,7 @@
dependencies:
"@types/unist" "*"
-"@types/hoist-non-react-statics@^3.3.0":
+"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@>= 3.3.1":
version "3.3.6"
resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz"
integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
@@ -2081,7 +2559,7 @@
resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz"
integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==
-"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9":
+"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9":
version "7.0.15"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
@@ -2113,7 +2591,7 @@
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
-"@types/node@*", "@types/node@>=8.1.0":
+"@types/node@*", "@types/node@>= 12", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.1.0":
version "20.4.2"
resolved "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz"
integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==
@@ -2148,7 +2626,7 @@
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
-"@types/react@*":
+"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@>= 16", "@types/react@>=0.0.0 <=99", "@types/react@>=18":
version "18.2.15"
resolved "https://registry.npmjs.org/@types/react/-/react-18.2.15.tgz"
integrity sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==
@@ -2348,6 +2826,127 @@
resolved "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.5.0.tgz"
integrity sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==
+"@webassemblyjs/ast@^1.14.1", "@webassemblyjs/ast@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz"
+ integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.13.2"
+ "@webassemblyjs/helper-wasm-bytecode" "1.13.2"
+
+"@webassemblyjs/floating-point-hex-parser@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz"
+ integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==
+
+"@webassemblyjs/helper-api-error@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz"
+ integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==
+
+"@webassemblyjs/helper-buffer@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz"
+ integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==
+
+"@webassemblyjs/helper-numbers@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz"
+ integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.13.2"
+ "@webassemblyjs/helper-api-error" "1.13.2"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz"
+ integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==
+
+"@webassemblyjs/helper-wasm-section@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz"
+ integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@webassemblyjs/helper-buffer" "1.14.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.13.2"
+ "@webassemblyjs/wasm-gen" "1.14.1"
+
+"@webassemblyjs/ieee754@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz"
+ integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz"
+ integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.13.2":
+ version "1.13.2"
+ resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz"
+ integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==
+
+"@webassemblyjs/wasm-edit@^1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz"
+ integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@webassemblyjs/helper-buffer" "1.14.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.13.2"
+ "@webassemblyjs/helper-wasm-section" "1.14.1"
+ "@webassemblyjs/wasm-gen" "1.14.1"
+ "@webassemblyjs/wasm-opt" "1.14.1"
+ "@webassemblyjs/wasm-parser" "1.14.1"
+ "@webassemblyjs/wast-printer" "1.14.1"
+
+"@webassemblyjs/wasm-gen@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz"
+ integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.13.2"
+ "@webassemblyjs/ieee754" "1.13.2"
+ "@webassemblyjs/leb128" "1.13.2"
+ "@webassemblyjs/utf8" "1.13.2"
+
+"@webassemblyjs/wasm-opt@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz"
+ integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@webassemblyjs/helper-buffer" "1.14.1"
+ "@webassemblyjs/wasm-gen" "1.14.1"
+ "@webassemblyjs/wasm-parser" "1.14.1"
+
+"@webassemblyjs/wasm-parser@^1.14.1", "@webassemblyjs/wasm-parser@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz"
+ integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@webassemblyjs/helper-api-error" "1.13.2"
+ "@webassemblyjs/helper-wasm-bytecode" "1.13.2"
+ "@webassemblyjs/ieee754" "1.13.2"
+ "@webassemblyjs/leb128" "1.13.2"
+ "@webassemblyjs/utf8" "1.13.2"
+
+"@webassemblyjs/wast-printer@1.14.1":
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz"
+ integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==
+ dependencies:
+ "@webassemblyjs/ast" "1.14.1"
+ "@xtuc/long" "4.2.2"
+
"@webcontainer/api@^1.5.1-internal.5":
version "1.5.3"
resolved "https://registry.npmjs.org/@webcontainer/api/-/api-1.5.3.tgz"
@@ -2358,20 +2957,35 @@
resolved "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz"
integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
accessor-fn@1:
version "1.5.3"
resolved "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz"
integrity sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==
+acorn-import-phases@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.3.tgz"
+ integrity sha512-jtKLnfoOzm28PazuQ4dVBcE9Jeo6ha1GAJvq3N0LlNOszmTfx+wSycBehn+FN0RnyeR77IBxN/qVYMw0Rlj0Xw==
+
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-acorn@^8.8.2, acorn@^8.9.0:
- version "8.14.1"
- resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
- integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
+"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0, acorn@^8.15.0, acorn@^8.8.2, acorn@^8.9.0:
+ version "8.15.0"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz"
+ integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
agent-base@^7.1.0, agent-base@^7.1.2:
version "7.1.3"
@@ -2397,7 +3011,7 @@ ajv-keywords@^5.1.0:
dependencies:
fast-deep-equal "^3.1.3"
-ajv@^6.10.0, ajv@^6.12.4:
+ajv@^6.10.0, ajv@^6.12.4, ajv@^6.9.1:
version "6.12.6"
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2417,7 +3031,7 @@ ajv@^8.0.0:
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
-ajv@^8.6.0:
+ajv@^8.6.0, ajv@>=8:
version "8.17.1"
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
@@ -2427,7 +3041,7 @@ ajv@^8.6.0:
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
-ajv@^8.9.0:
+ajv@^8.8.2, ajv@^8.9.0:
version "8.17.1"
resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz"
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
@@ -2702,7 +3316,7 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-bare-events@^2.2.0, bare-events@^2.5.4:
+bare-events@*, bare-events@^2.2.0, bare-events@^2.5.4:
version "2.5.4"
resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz"
integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==
@@ -2787,7 +3401,7 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
-browserslist@^4.21.5, browserslist@^4.24.0, browserslist@^4.24.4:
+browserslist@^4.21.5, browserslist@^4.24.0, browserslist@^4.24.4, "browserslist@>= 4.21.0":
version "4.24.4"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz"
integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==
@@ -2904,7 +3518,7 @@ character-reference-invalid@^2.0.0:
resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz"
integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==
-chart.js@^4.4.3:
+chart.js@^4.1.1, chart.js@^4.4.3:
version "4.4.9"
resolved "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz"
integrity sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==
@@ -2926,6 +3540,11 @@ chokidar@^3.5.3:
optionalDependencies:
fsevents "~2.3.2"
+chrome-trace-event@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz"
+ integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==
+
chromium-bidi@0.6.3:
version "0.6.3"
resolved "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz"
@@ -3535,7 +4154,7 @@ devlop@^1.0.0, devlop@^1.1.0:
dependencies:
dequal "^2.0.0"
-devtools-protocol@0.0.1312386:
+devtools-protocol@*, devtools-protocol@0.0.1312386:
version "0.0.1312386"
resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz"
integrity sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==
@@ -3612,7 +4231,7 @@ earcut@3:
resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz"
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
-easymde@^2.18.0:
+easymde@^2.18.0, "easymde@>= 2.0.0 < 3.0.0":
version "2.18.0"
resolved "https://registry.npmjs.org/easymde/-/easymde-2.18.0.tgz"
integrity sha512-IxVVUxNWIoXLeqtBU4BLc+eS/ScYhT1Dcb6yF5Wchoj1iXAV+TIIDWx+NCaZhY7RcSHqDPKllbYq7nwGKILnoA==
@@ -3678,6 +4297,14 @@ engine.io-parser@~5.2.1:
resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz"
integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==
+enhanced-resolve@^5.17.2:
+ version "5.18.2"
+ resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz"
+ integrity sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
entities@^4.5.0:
version "4.5.0"
resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
@@ -3757,6 +4384,11 @@ es-errors@^1.3.0:
resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz"
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
+es-module-lexer@^1.2.1:
+ version "1.7.0"
+ resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz"
+ integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==
+
es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz"
@@ -3863,7 +4495,7 @@ eslint-module-utils@^2.7.4:
dependencies:
debug "^3.2.7"
-eslint-plugin-import@^2.26.0:
+eslint-plugin-import@*, eslint-plugin-import@^2.26.0:
version "2.27.5"
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz"
integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==
@@ -3940,6 +4572,14 @@ eslint-scope@^7.1.1:
esrecurse "^4.3.0"
estraverse "^5.2.0"
+eslint-scope@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
eslint-utils@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz"
@@ -3957,7 +4597,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz"
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
-eslint@8.26.0:
+eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^7.23.0 || ^8.0.0", eslint@>=5, eslint@>=7.0.0, eslint@8.26.0:
version "8.26.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz"
integrity sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==
@@ -4030,6 +4670,11 @@ esrecurse@^4.3.0:
dependencies:
estraverse "^5.2.0"
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
version "5.3.0"
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
@@ -4055,6 +4700,11 @@ eventemitter3@^4.0.0, eventemitter3@^4.0.1:
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
extend@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz"
@@ -4129,6 +4779,13 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
+faye-websocket@0.11.4:
+ version "0.11.4"
+ resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz"
+ integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz"
@@ -4203,6 +4860,40 @@ find-up@^6.3.0:
locate-path "^7.1.0"
path-exists "^5.0.0"
+"firebase@>= 9.0.0":
+ version "11.10.0"
+ resolved "https://registry.npmjs.org/firebase/-/firebase-11.10.0.tgz"
+ integrity sha512-nKBXoDzF0DrXTBQJlZa+sbC5By99ysYU1D6PkMRYknm0nCW7rJly47q492Ht7Ndz5MeYSBuboKuhS1e6mFC03w==
+ dependencies:
+ "@firebase/ai" "1.4.1"
+ "@firebase/analytics" "0.10.17"
+ "@firebase/analytics-compat" "0.2.23"
+ "@firebase/app" "0.13.2"
+ "@firebase/app-check" "0.10.1"
+ "@firebase/app-check-compat" "0.3.26"
+ "@firebase/app-compat" "0.4.2"
+ "@firebase/app-types" "0.9.3"
+ "@firebase/auth" "1.10.8"
+ "@firebase/auth-compat" "0.5.28"
+ "@firebase/data-connect" "0.3.10"
+ "@firebase/database" "1.0.20"
+ "@firebase/database-compat" "2.0.11"
+ "@firebase/firestore" "4.8.0"
+ "@firebase/firestore-compat" "0.3.53"
+ "@firebase/functions" "0.12.9"
+ "@firebase/functions-compat" "0.3.26"
+ "@firebase/installations" "0.6.18"
+ "@firebase/installations-compat" "0.2.18"
+ "@firebase/messaging" "0.12.22"
+ "@firebase/messaging-compat" "0.2.22"
+ "@firebase/performance" "0.7.7"
+ "@firebase/performance-compat" "0.2.20"
+ "@firebase/remote-config" "0.6.5"
+ "@firebase/remote-config-compat" "0.2.18"
+ "@firebase/storage" "0.13.14"
+ "@firebase/storage-compat" "0.3.24"
+ "@firebase/util" "1.12.1"
+
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz"
@@ -4402,6 +5093,11 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
glob@^7.0.3, glob@^7.1.3, glob@^7.1.6, glob@^7.2.0:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
@@ -4497,7 +5193,7 @@ gopd@^1.0.1, gopd@^1.2.0:
resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz"
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
-graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11:
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4:
version "4.2.11"
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -4770,6 +5466,11 @@ html-void-elements@^3.0.0:
resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz"
integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==
+http-parser-js@>=0.5.1:
+ version "0.5.10"
+ resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz"
+ integrity sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==
+
http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1:
version "7.0.2"
resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz"
@@ -4791,7 +5492,7 @@ hyphenate-style-name@^1.0.0, hyphenate-style-name@^1.0.3:
resolved "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz"
integrity sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==
-idb@^7.0.1:
+idb@^7.0.1, idb@7.1.1:
version "7.1.1"
resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz"
integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==
@@ -5175,7 +5876,7 @@ jsesc@~3.0.2:
resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz"
integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
-json-parse-even-better-errors@^2.3.0:
+json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
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==
@@ -5293,6 +5994,11 @@ lines-and-columns@^1.1.6:
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
loader-utils@^2.0.4:
version "2.0.4"
resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz"
@@ -5328,6 +6034,11 @@ lodash-es@4:
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+lodash.camelcase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz"
+ integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
+
lodash.debounce@^4.0.8, lodash.debounce@4.0.8:
version "4.0.8"
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
@@ -5348,6 +6059,11 @@ lodash@^4.17.20, lodash@^4.17.21:
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+long@^5.0.0:
+ version "5.3.2"
+ resolved "https://registry.npmjs.org/long/-/long-5.3.2.tgz"
+ integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==
+
longest-streak@^3.0.0:
version "3.1.0"
resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz"
@@ -5921,7 +6637,7 @@ mime-db@1.52.0:
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-mime-types@^2.1.12:
+mime-types@^2.1.12, mime-types@^2.1.27:
version "2.1.35"
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@@ -5957,6 +6673,11 @@ mitt@3.0.1:
resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz"
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
+"monaco-editor@>= 0.25.0 < 1":
+ version "0.52.2"
+ resolved "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz"
+ integrity sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==
+
motion-dom@^11.18.1:
version "11.18.1"
resolved "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz"
@@ -6017,6 +6738,11 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
netmask@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz"
@@ -6043,7 +6769,7 @@ next-remove-imports@^1.0.12:
babel-loader "^9.1.3"
babel-plugin-transform-remove-imports "^1.7.0"
-next@^14.0.2:
+next@^14.0.2, "next@>= 13", next@>=9.0.0:
version "14.2.28"
resolved "https://registry.npmjs.org/next/-/next-14.2.28.tgz"
integrity sha512-QLEIP/kYXynIxtcKB6vNjtWLVs3Y4Sb+EClTC/CSVzdLD1gIuItccpu/n1lhmduffI32iPGEK2cLLxxt28qgYA==
@@ -6476,7 +7202,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
-postcss@^8.4.23, postcss@8.4.49:
+postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9, postcss@8.4.49:
version "8.4.49"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz"
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
@@ -6509,7 +7235,7 @@ prettier-plugin-tailwindcss@^0.1.13:
resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.13.tgz"
integrity sha512-/EKQURUrxLu66CMUg4+1LwGdxnz8of7IDvrSLqEtDqhLH61SAlNNUSr90UTvZaemujgl3OH/VHg+fyGltrNixw==
-prettier@^2.7.1:
+prettier@^2.7.1, prettier@>=2.2.0:
version "2.8.8"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
@@ -6552,6 +7278,24 @@ property-information@^7.0.0:
resolved "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz"
integrity sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==
+protobufjs@^7.2.5:
+ version "7.5.3"
+ resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz"
+ integrity sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==
+ dependencies:
+ "@protobufjs/aspromise" "^1.1.2"
+ "@protobufjs/base64" "^1.1.2"
+ "@protobufjs/codegen" "^2.0.4"
+ "@protobufjs/eventemitter" "^1.1.0"
+ "@protobufjs/fetch" "^1.1.0"
+ "@protobufjs/float" "^1.0.2"
+ "@protobufjs/inquire" "^1.1.0"
+ "@protobufjs/path" "^1.1.2"
+ "@protobufjs/pool" "^1.1.0"
+ "@protobufjs/utf8" "^1.1.0"
+ "@types/node" ">=13.7.0"
+ long "^5.0.0"
+
proxy-agent@^6.4.0:
version "6.5.0"
resolved "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz"
@@ -6703,7 +7447,7 @@ react-dnd@^16.0.1:
fast-deep-equal "^3.1.3"
hoist-non-react-statics "^3.3.2"
-react-dom@18.2.0:
+react-dom@*, "react-dom@^15.0.1 || ^16.0.1", "react-dom@^16 || ^17 || ^18", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.3.0 || ^17.0.0-0 || ^18.0.0-0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || 17.x || 18.x", "react-dom@^16.8.5 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0", react-dom@^18.2.0, "react-dom@>= 16.3.0", "react-dom@>= 16.8.0", react-dom@>=16, react-dom@>=16.0.0, react-dom@>=16.14.0, react-dom@>=16.3.0, react-dom@>=16.4.0, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0, react-dom@>=16.8.2, react-dom@>=18, "react-dom@~15 || ~16 || ~17 || ~18", "react-dom@15 - 18", react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
@@ -6799,6 +7543,11 @@ react-is@^16.7.0:
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+"react-is@^16.8 || ^17.0.0-0 || ^18.0.0-0", react-is@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz"
+ integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
+
react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
@@ -6809,11 +7558,6 @@ react-is@^17.0.2:
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-react-is@^18.3.1:
- version "18.3.1"
- resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz"
- integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
-
react-is@^19.0.0:
version "19.1.0"
resolved "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz"
@@ -7059,7 +7803,7 @@ react-visibility-sensor@^5.1.1:
dependencies:
prop-types "^15.7.2"
-react@18.2.0:
+react@*, "react@^0.14.9 || ^15.3.0 || ^16.0.0", "react@^15.0.1 || ^16.0.1", "react@^16 || ^17 || ^18", "react@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.3.0 || ^17.0.0-0 || ^18.0.0-0", "react@^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || 17.x || 18.x", "react@^16.8.3 || ^17 || ^18", "react@^16.8.3 || ^17 || ^18 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.5 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19 || ^19.0.0-rc", react@^18.0.0, "react@^18.0.0 || ^19.0.0", react@^18.2.0, "react@>= 16", "react@>= 16.14", "react@>= 16.3", "react@>= 16.3.0", "react@>= 16.8.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>=0.0.0 <=99", react@>=0.14.0, react@>=16, react@>=16.0.0, react@>=16.13.1, react@>=16.14.0, react@>=16.3, react@>=16.3.0, react@>=16.4.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.8.2, react@>=18, react@>=18.0.0, "react@~15 || ~16 || ~17 || ~18", "react@15 - 18", react@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
@@ -7418,7 +8162,7 @@ rollup-plugin-terser@^7.0.0:
serialize-javascript "^4.0.0"
terser "^5.0.0"
-rollup@^2.43.1:
+"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.43.1:
version "2.79.2"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
@@ -7449,7 +8193,7 @@ safe-array-concat@^1.0.0:
has-symbols "^1.0.3"
isarray "^2.0.5"
-safe-buffer@^5.1.0:
+safe-buffer@^5.1.0, safe-buffer@>=5.1.0:
version "5.2.1"
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -7499,6 +8243,16 @@ schema-utils@^4.3.0:
ajv-formats "^2.1.1"
ajv-keywords "^5.1.0"
+schema-utils@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz"
+ integrity sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.9.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.1.0"
+
screenfull@^5.1.0:
version "5.2.0"
resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz"
@@ -7560,7 +8314,7 @@ seroval-plugins@^1.1.0:
resolved "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.2.1.tgz"
integrity sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw==
-seroval@^1.1.0:
+seroval@^1.0, seroval@^1.1.0:
version "1.2.1"
resolved "https://registry.npmjs.org/seroval/-/seroval-1.2.1.tgz"
integrity sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw==
@@ -7930,7 +8684,7 @@ style-to-object@1.0.8:
dependencies:
inline-style-parser "0.2.4"
-styled-components@^6.1.13:
+"styled-components@^4.0.0 || ^5.0.0", styled-components@^6.1.13:
version "6.1.17"
resolved "https://registry.npmjs.org/styled-components/-/styled-components-6.1.17.tgz"
integrity sha512-97D7DwWanI7nN24v0D4SvbfjLE9656umNSJZkBkDIWL37aZqG/wRQ+Y9pWtXyBIM/NSfcBzHLErEsqHmJNSVUg==
@@ -8009,7 +8763,7 @@ tailwindcss-animate@^1.0.7:
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
-tailwindcss@^3.2.1:
+tailwindcss@^3.2.1, "tailwindcss@>=3.0.0 || >= 3.0.0-alpha.1", "tailwindcss@>=3.0.0 || insiders":
version "3.3.3"
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz"
integrity sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==
@@ -8037,6 +8791,11 @@ tailwindcss@^3.2.1:
resolve "^1.22.2"
sucrase "^3.32.0"
+tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz"
+ integrity sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==
+
tar-fs@^3.0.6:
version "3.0.8"
resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz"
@@ -8072,7 +8831,7 @@ tempy@^0.6.0:
type-fest "^0.16.0"
unique-string "^2.0.0"
-terser-webpack-plugin@^5.3.3:
+terser-webpack-plugin@^5.3.11, terser-webpack-plugin@^5.3.3:
version "5.3.14"
resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz"
integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==
@@ -8184,7 +8943,7 @@ three-slippy-map-globe@1:
d3-octree "^1.1"
d3-scale "1 - 4"
-three@^0.175.0, "three@>=0.154 <1":
+three@^0.175.0, three@>=0.154, "three@>=0.154 <1", three@>=0.168, three@>=0.72.0:
version "0.175.0"
resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz"
integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==
@@ -8293,16 +9052,16 @@ tsconfig-paths@^3.14.1:
minimist "^1.2.6"
strip-bom "^3.0.0"
+tslib@*, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@2.6.2:
+ version "2.6.2"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
+
tslib@^1.8.1:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@2.6.2:
- version "2.6.2"
- resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
- integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
-
tslib@^2.8.1:
version "2.8.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
@@ -8381,6 +9140,11 @@ typed-array-length@^1.0.4:
for-each "^0.3.3"
is-typed-array "^1.1.9"
+"typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=3.3.1, typescript@>=4.9.5:
+ version "5.8.3"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
+ integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
+
typo-js@*:
version "1.2.3"
resolved "https://registry.npmjs.org/typo-js/-/typo-js-1.2.3.tgz"
@@ -8603,11 +9367,24 @@ w3c-keyname@^2.2.4:
resolved "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz"
integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
+watchpack@^2.4.1:
+ version "2.4.4"
+ resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz"
+ integrity sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
web-namespaces@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz"
integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==
+web-vitals@^4.2.4:
+ version "4.2.4"
+ resolved "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz"
+ integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==
+
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz"
@@ -8626,6 +9403,56 @@ webpack-sources@^1.4.3:
source-list-map "^2.0.0"
source-map "~0.6.1"
+webpack-sources@^3.3.3:
+ version "3.3.3"
+ resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz"
+ integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==
+
+"webpack@^4.4.0 || ^5.9.0", webpack@^5.1.0, webpack@>=2, "webpack@>=4.0.0 <6.0.0", webpack@>=5:
+ version "5.100.1"
+ resolved "https://registry.npmjs.org/webpack/-/webpack-5.100.1.tgz"
+ integrity sha512-YJB/ESPUe2Locd0NKXmw72Dx8fZQk1gTzI6rc9TAT4+Sypbnhl8jd8RywB1bDsDF9Dy1RUR7gn3q/ZJTd0OZZg==
+ dependencies:
+ "@types/eslint-scope" "^3.7.7"
+ "@types/estree" "^1.0.8"
+ "@types/json-schema" "^7.0.15"
+ "@webassemblyjs/ast" "^1.14.1"
+ "@webassemblyjs/wasm-edit" "^1.14.1"
+ "@webassemblyjs/wasm-parser" "^1.14.1"
+ acorn "^8.15.0"
+ acorn-import-phases "^1.0.3"
+ browserslist "^4.24.0"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.17.2"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.11"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^4.3.2"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.11"
+ watchpack "^2.4.1"
+ webpack-sources "^3.3.3"
+
+websocket-driver@>=0.5.1:
+ version "0.7.4"
+ resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+ dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.4"
+ resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz"
@@ -8875,7 +9702,7 @@ xterm-addon-fit@^0.8.0:
resolved "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz"
integrity sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw==
-xterm@^5.3.0:
+xterm@^5.0.0, xterm@^5.3.0:
version "5.3.0"
resolved "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz"
integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==
From 94e222edcb109137ccae6d6dc84944f2d4da0e41 Mon Sep 17 00:00:00 2001
From: Sai4158 <116776995+Sai4158@users.noreply.github.com>
Date: Tue, 15 Jul 2025 22:32:50 -0400
Subject: [PATCH 2/4] New report page, moderation page and able to disable and
delete accounts
---
src/components/AccountReactivation.jsx | 395 ++
src/components/CommentReporter.jsx | 219 +
.../moderation/UserActionModals.jsx | 144 +
src/components/moderation/ViewChallenge.jsx | 16 +-
src/components/moderation/ViewReport.jsx | 67 +-
src/components/settingComponents/dropdown.jsx | 11 +-
src/components/settingComponents/sidebar.jsx | 21 +-
src/pages/dashboard.jsx | 773 ++-
src/pages/login.jsx | 217 +-
src/pages/moderation.jsx | 4532 ++++++++++++++---
src/pages/report.jsx | 648 ++-
src/pages/settings/account-management.jsx | 1003 ++++
src/utils/request.js | 105 +-
13 files changed, 6980 insertions(+), 1171 deletions(-)
create mode 100644 src/components/AccountReactivation.jsx
create mode 100644 src/components/CommentReporter.jsx
create mode 100644 src/components/moderation/UserActionModals.jsx
create mode 100644 src/pages/settings/account-management.jsx
diff --git a/src/components/AccountReactivation.jsx b/src/components/AccountReactivation.jsx
new file mode 100644
index 00000000..07149308
--- /dev/null
+++ b/src/components/AccountReactivation.jsx
@@ -0,0 +1,395 @@
+import React, { useState, useEffect } from 'react';
+import request from '@/utils/request';
+
+const AccountReactivation = ({
+ email,
+ accountType,
+ password,
+ deletionInfo,
+ onReactivated,
+ onCancel,
+}) => {
+ const [isReactivating, setIsReactivating] = useState(false);
+ const [notification, setNotification] = useState(null);
+ const [detectedAccountType, setDetectedAccountType] = useState(
+ accountType || 'EMAIL'
+ );
+
+ // Detect account type on mount
+ useEffect(() => {
+ if (accountType) {
+ setDetectedAccountType(accountType);
+ }
+ }, [accountType]);
+
+ const showNotification = (message, type = 'info') => {
+ setNotification({ message, type });
+ setTimeout(() => setNotification(null), 5000);
+ };
+
+ // Calculate deletion deadline
+ const getDeletionInfo = () => {
+ if (!deletionInfo?.scheduledFor) {
+ return {
+ hasDeadline: false,
+ message: 'Your account deletion is pending.',
+ };
+ }
+
+ try {
+ const deadline = new Date(deletionInfo.scheduledFor);
+ const now = new Date();
+ const timeRemaining = deadline.getTime() - now.getTime();
+ const daysRemaining = Math.max(
+ 0,
+ Math.ceil(timeRemaining / (1000 * 60 * 60 * 24))
+ );
+ const hoursRemaining = Math.max(
+ 0,
+ Math.ceil(timeRemaining / (1000 * 60 * 60))
+ );
+
+ if (timeRemaining > 0) {
+ return {
+ hasDeadline: true,
+ deadline: deadline.toLocaleDateString(),
+ daysRemaining,
+ hoursRemaining,
+ message: `You have ${daysRemaining} day(s) to save your account!`,
+ urgency:
+ daysRemaining <= 1 ? 'high' : daysRemaining <= 3 ? 'medium' : 'low',
+ };
+ } else {
+ return {
+ hasDeadline: false,
+ message: 'Your deletion deadline has passed.',
+ };
+ }
+ } catch (error) {
+ return {
+ hasDeadline: false,
+ message: 'Your account deletion is pending.',
+ };
+ }
+ };
+
+ const deletionData = getDeletionInfo();
+
+ const handleReactivation = async () => {
+ setIsReactivating(true);
+ try {
+ // Validate that we have password for EMAIL accounts
+ if (detectedAccountType === 'EMAIL' && !password) {
+ throw new Error(
+ 'Password is required for email accounts. Please try logging in again.'
+ );
+ }
+
+ const requestData = {
+ email: email,
+ accountType: detectedAccountType,
+ };
+
+ // Include password for EMAIL accounts
+ if (detectedAccountType === 'EMAIL' && password) {
+ requestData.password = password;
+ }
+
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/account/reactivate`,
+ 'POST',
+ requestData
+ );
+
+ if (response.success) {
+ const successMessage = deletionInfo
+ ? 'Account saved successfully! Your deletion has been cancelled.'
+ : 'Account reactivated successfully!';
+ showNotification(successMessage, 'success');
+
+ // Store the token securely
+ if (response.token) {
+ localStorage.setItem('token', response.token);
+ }
+
+ setTimeout(() => {
+ onReactivated?.(response.token);
+ }, 1500);
+ } else {
+ throw new Error(response.error || 'Failed to reactivate account');
+ }
+ } catch (error) {
+ let errorMessage = error.message || 'Failed to reactivate account.';
+
+ // Handle specific error cases
+ if (errorMessage.includes('Password is required')) {
+ errorMessage =
+ 'Password verification failed. Please go back and try logging in again.';
+ } else if (errorMessage.includes('Invalid password')) {
+ errorMessage =
+ 'The password you entered is incorrect. Please go back and try again.';
+ }
+
+ showNotification(errorMessage, 'error');
+ } finally {
+ setIsReactivating(false);
+ }
+ };
+
+ const NotificationModal = () => {
+ if (!notification) return null;
+
+ const getIcon = () => {
+ switch (notification.type) {
+ case 'success':
+ return 'fas fa-check-circle text-green-400';
+ case 'error':
+ return 'fas fa-exclamation-circle text-red-400';
+ case 'warning':
+ return 'fas fa-exclamation-triangle text-yellow-400';
+ default:
+ return 'fas fa-info-circle text-blue-400';
+ }
+ };
+
+ return (
+
+
setNotification(null)}
+ />
+
+
+
+
+
{notification.message}
+
+
setNotification(null)}
+ className="text-gray-400 transition-colors hover:text-white"
+ >
+
+
+
+
+
+ );
+ };
+
+ return (
+ <>
+
+
+ {/* Header */}
+
+
+ {/* Main Card */}
+
+ {/* Title */}
+
+
+ {deletionInfo && deletionData.hasDeadline
+ ? 'Save Your Account from Permanent Deletion'
+ : deletionInfo
+ ? 'Account Deletion Request'
+ : 'Account Reactivation'}
+
+
+ {deletionInfo && deletionData.hasDeadline
+ ? `Login before ${deletionData.deadline} to prevent permanent deletion`
+ : deletionInfo
+ ? 'Your account deletion request is pending'
+ : 'Your account is temporarily suspended'}
+
+
+
+ {/* Deletion Deadline Warning - Only show if account deletion is scheduled */}
+ {deletionInfo && deletionData.hasDeadline && (
+
+
+
+
+
+
+
+ Deleting in {deletionData.daysRemaining} day(s)
+
+
+ Scheduled: {deletionData.deadline}
+
+ {deletionData.daysRemaining <= 3 && (
+
+ {deletionData.daysRemaining}d,{' '}
+ {deletionData.hoursRemaining % 24}h remaining
+
+ )}
+
+
+
+ )}
+
+ {/* Account Info */}
+
+
+
+ {detectedAccountType === 'GOOGLE' ? (
+
+ ) : (
+
+ )}
+
+
+
{email}
+
+ {detectedAccountType === 'GOOGLE'
+ ? 'Google Account'
+ : 'Email Account'}
+
+
+
+
+
+
+
+
+ {/* Info Cards */}
+
+
+
+ What happened?
+
+
+ {deletionInfo
+ ? 'You requested account deletion and your account has been suspended for 7 days as a safety measure.'
+ : 'Your account has been temporarily suspended but can be reactivated instantly.'}
+
+
+
+
+
+ {deletionInfo ? 'Your content is still safe!' : 'Good news!'}
+
+
+ {deletionInfo
+ ? 'All your challenges, comments, and progress remain visible and intact during this 7-day period. Nothing is transferred to the system account until the deadline passes.'
+ : 'All your data is safe and will be restored immediately upon reactivation.'}
+
+
+
+
+ {/* Ready to Reactivate Notice */}
+
+
+
+
+
+
+
+ {deletionInfo
+ ? 'Ready to Cancel Deletion'
+ : 'Ready to Reactivate'}
+
+
+ {deletionInfo
+ ? 'Click below to immediately cancel your deletion request'
+ : "You're already authenticated - just click the button below"}
+
+
+
+
+
+ {/* Buttons */}
+
+
+ {isReactivating ? (
+ <>
+
+ {deletionInfo
+ ? 'Cancelling Deletion...'
+ : 'Reactivating...'}
+ >
+ ) : (
+ <>
+
+ {deletionInfo
+ ? 'Cancel Deletion & Keep My Account'
+ : 'Reactivate Account'}
+ >
+ )}
+
+
+
+ Back to Login
+
+
+
+ {/* Footer */}
+
+
+
+ {/* Bottom Footer */}
+
+
© CTFGuide Corporation 2025
+
+
+
+
+
+ >
+ );
+};
+
+export default AccountReactivation;
diff --git a/src/components/CommentReporter.jsx b/src/components/CommentReporter.jsx
new file mode 100644
index 00000000..a05815fc
--- /dev/null
+++ b/src/components/CommentReporter.jsx
@@ -0,0 +1,219 @@
+import React, { useState } from 'react';
+import request from '@/utils/request';
+
+const CommentReporter = ({ commentId, commentContent, challengeId }) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ const [selectedReason, setSelectedReason] = useState('');
+ const [customReason, setCustomReason] = useState('');
+ const [notification, setNotification] = useState(null);
+
+ const reportReasons = [
+ { value: 'SPAM', label: 'Spam or unwanted commercial content' },
+ { value: 'HARASSMENT', label: 'Harassment or bullying' },
+ { value: 'INAPPROPRIATE', label: 'Inappropriate content' },
+ { value: 'MISINFORMATION', label: 'False or misleading information' },
+ { value: 'SPOILER', label: 'Contains spoilers or solution hints' },
+ { value: 'OFF_TOPIC', label: 'Off-topic or irrelevant' },
+ { value: 'OTHER', label: 'Other (please specify)' },
+ ];
+
+ const showNotification = (message, type = 'info') => {
+ setNotification({ message, type });
+ setTimeout(() => setNotification(null), 4000);
+ };
+
+ const handleSubmitReport = async () => {
+ if (!selectedReason) {
+ showNotification('Please select a reason for reporting', 'error');
+ return;
+ }
+
+ if (selectedReason === 'OTHER' && !customReason.trim()) {
+ showNotification('Please provide a custom reason', 'error');
+ return;
+ }
+
+ setIsSubmitting(true);
+
+ try {
+ const reportData = {
+ type: 'COMMENT',
+ desc:
+ selectedReason === 'OTHER'
+ ? customReason
+ : reportReasons.find((r) => r.value === selectedReason)?.label,
+ metadata: {
+ commentId,
+ challengeId,
+ reason: selectedReason,
+ commentContent: commentContent?.substring(0, 200) || '', // First 200 chars for context
+ },
+ };
+
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/reports`,
+ 'POST',
+ reportData
+ );
+
+ if (response.success) {
+ showNotification(
+ 'Comment reported successfully. Thank you for helping keep our community safe.',
+ 'success'
+ );
+ setIsOpen(false);
+ setSelectedReason('');
+ setCustomReason('');
+ } else {
+ throw new Error(response.error || 'Failed to submit report');
+ }
+ } catch (error) {
+ console.error('Error reporting comment:', error);
+ showNotification(
+ error.message || 'Failed to submit report. Please try again.',
+ 'error'
+ );
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
+ const NotificationModal = () => {
+ if (!notification) return null;
+
+ const getIcon = () => {
+ switch (notification.type) {
+ case 'success':
+ return 'fas fa-check-circle text-green-400';
+ case 'error':
+ return 'fas fa-exclamation-circle text-red-400';
+ case 'warning':
+ return 'fas fa-exclamation-triangle text-yellow-400';
+ default:
+ return 'fas fa-info-circle text-blue-400';
+ }
+ };
+
+ return (
+
+
setNotification(null)}
+ />
+
+
+
+
+
{notification.message}
+
+
setNotification(null)}
+ className="text-gray-400 transition-colors hover:text-white"
+ >
+
+
+
+
+
+ );
+ };
+
+ return (
+ <>
+
setIsOpen(true)}
+ className="text-sm text-gray-400 transition-colors duration-200 hover:text-red-400"
+ title="Report this comment"
+ >
+
+ Report
+
+
+ {isOpen && (
+
+
setIsOpen(false)}
+ />
+
+
+
+ Report Comment
+
+ setIsOpen(false)}
+ className="text-gray-400 transition-colors hover:text-white"
+ >
+
+
+
+
+
+ Help us keep the community safe by reporting inappropriate
+ content.
+
+
+
+ {reportReasons.map((reason) => (
+
+ setSelectedReason(e.target.value)}
+ className="border-neutral-600 bg-neutral-700 text-blue-600 focus:ring-blue-500"
+ />
+
+ {reason.label}
+
+
+ ))}
+
+
+ {selectedReason === 'OTHER' && (
+
+
+ )}
+
+
+ >
+ );
+};
+
+export default CommentReporter;
diff --git a/src/components/moderation/UserActionModals.jsx b/src/components/moderation/UserActionModals.jsx
new file mode 100644
index 00000000..7f8e2637
--- /dev/null
+++ b/src/components/moderation/UserActionModals.jsx
@@ -0,0 +1,144 @@
+import React from 'react';
+
+const UserActionModals = ({
+ // Suspend modal props
+ showSuspendModal,
+ setShowSuspendModal,
+ suspendForm,
+ setSuspendForm,
+ submitSuspension,
+
+ // Role modal props
+ showRoleModal,
+ setShowRoleModal,
+ roleForm,
+ setRoleForm,
+ submitRoleChange,
+
+ // Common props
+ selectedUserForAction,
+}) => {
+ return (
+ <>
+ {/* Suspend Modal */}
+ {showSuspendModal && (
+
+
+
+ Suspend User
+
+
+ Suspending user:{' '}
+
+ {selectedUserForAction?.username}
+
+
+
+
+
+
+ Reason for Suspension
+
+
+
+
+
+ Duration (hours)
+
+
+ setSuspendForm({ ...suspendForm, duration: e.target.value })
+ }
+ className="w-full border border-neutral-600 bg-neutral-700 p-3 text-white focus:border-blue-500 focus:outline-none"
+ placeholder="Leave empty for indefinite suspension"
+ min="1"
+ />
+
+ Leave empty for permanent suspension
+
+
+
+
+
+ setShowSuspendModal(false)}
+ className="flex-1 bg-neutral-600 px-4 py-2 text-white transition-colors duration-200 hover:bg-neutral-500"
+ >
+ Cancel
+
+
+ Suspend User
+
+
+
+
+ )}
+
+ {/* Role Change Modal */}
+ {showRoleModal && (
+
+
+
+ Change User Role
+
+
+ Changing role for:{' '}
+
+ {selectedUserForAction?.username}
+
+
+
+
+
+
+ Select New Role
+
+
+ setRoleForm({ ...roleForm, role: e.target.value })
+ }
+ className="w-full border border-neutral-600 bg-neutral-700 p-3 text-white focus:border-blue-500 focus:outline-none"
+ >
+ User (Standard Account)
+ Pro (Premium Features)
+ Admin (Full Access)
+
+
+
+
+
+ setShowRoleModal(false)}
+ className="flex-1 bg-neutral-600 px-4 py-2 text-white transition-colors duration-200 hover:bg-neutral-500"
+ >
+ Cancel
+
+
+ Update Role
+
+
+
+
+ )}
+ >
+ );
+};
+
+export default UserActionModals;
diff --git a/src/components/moderation/ViewChallenge.jsx b/src/components/moderation/ViewChallenge.jsx
index a40ffdb2..46e79d85 100644
--- a/src/components/moderation/ViewChallenge.jsx
+++ b/src/components/moderation/ViewChallenge.jsx
@@ -78,7 +78,7 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
setOpen(false)}
>
@@ -100,7 +100,7 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
Description
-
+
Flag
@@ -170,7 +170,7 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
-
+
Set Base Points
Beginner: 100 ,
@@ -191,18 +191,18 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
setOpen(false)}
>
Cancel
-
window.open(`../../challenges/${selected}`, '_blank')}>
+ window.open(`../../challenges/${selected}`, '_blank')}>
Go to Challenge Page
- window.open(`../../create/edit?id=${selected}`, '_blank')}>
+ window.open(`../../create/edit?id=${selected}`, '_blank')}>
Edit Challenge
@@ -223,7 +223,7 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
}
}}
type="button"
- className="ml-4 justify-center rounded-md bg-yellow-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-yellow-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-yellow-500"
+ className="ml-4 justify-center bg-yellow-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-yellow-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-yellow-500"
>
Request Changes
@@ -244,7 +244,7 @@ const ViewChallenge = ({ open, setOpen, selected }) => {
}
}}
type="submit"
- className="ml-4 justify-center rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-500"
+ className="ml-4 justify-center bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-500"
>
{isLoading ? (
diff --git a/src/components/moderation/ViewReport.jsx b/src/components/moderation/ViewReport.jsx
index ab10eb04..0223db29 100644
--- a/src/components/moderation/ViewReport.jsx
+++ b/src/components/moderation/ViewReport.jsx
@@ -1,10 +1,12 @@
-import { Fragment } from 'react'
-import { Dialog, Transition } from '@headlessui/react'
+import { Fragment } from 'react';
+import { Dialog, Transition } from '@headlessui/react';
export default function ViewReport({ open, setOpen, report }) {
// Parse metadata if it exists and is a string
- const metadata = report?.metadata ?
- (typeof report.metadata === 'string' ? JSON.parse(report.metadata) : report.metadata)
+ const metadata = report?.metadata
+ ? typeof report.metadata === 'string'
+ ? JSON.parse(report.metadata)
+ : report.metadata
: {};
return (
@@ -33,10 +35,13 @@ export default function ViewReport({ open, setOpen, report }) {
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
-
+
-
+
Report Details
@@ -49,15 +54,14 @@ export default function ViewReport({ open, setOpen, report }) {
{metadata.reportedUserId && (
)}
@@ -79,12 +83,18 @@ export default function ViewReport({ open, setOpen, report }) {
Severity:
-
+
{metadata.severity}
@@ -100,14 +110,15 @@ export default function ViewReport({ open, setOpen, report }) {
Description:
-
- {report?.desc}
-
+
{report?.desc}
Submitted:
-
{report?.createdAt && new Date(report.createdAt).toLocaleString()}
+
+ {report?.createdAt &&
+ new Date(report.createdAt).toLocaleString()}
+
@@ -116,7 +127,7 @@ export default function ViewReport({ open, setOpen, report }) {
setOpen(false)}
>
Close
@@ -128,5 +139,5 @@ export default function ViewReport({ open, setOpen, report }) {
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/src/components/settingComponents/dropdown.jsx b/src/components/settingComponents/dropdown.jsx
index a3205e58..b0dc2323 100644
--- a/src/components/settingComponents/dropdown.jsx
+++ b/src/components/settingComponents/dropdown.jsx
@@ -4,17 +4,20 @@ export default function Dropdown({ tab }) {
const router = useRouter();
return (
-
+
router.push(e.target.value, null, { shallow: true })}
>
General
Security
Email Preferences
Billing
+
+ Account Management
+
);
-}
\ No newline at end of file
+}
diff --git a/src/components/settingComponents/sidebar.jsx b/src/components/settingComponents/sidebar.jsx
index 6514ae0e..6cb21b0b 100644
--- a/src/components/settingComponents/sidebar.jsx
+++ b/src/components/settingComponents/sidebar.jsx
@@ -1,8 +1,8 @@
import Link from 'next/link';
-import { useRouter } from 'next/router'
+import { useRouter } from 'next/router';
export default function Sidebar() {
- const router = useRouter()
+ const router = useRouter();
return (
+
+ {/* Divider */}
+
+
+
+
+ {/* Account Management Section */}
+
+
+
+
+
);
-}
\ No newline at end of file
+}
diff --git a/src/pages/dashboard.jsx b/src/pages/dashboard.jsx
index c0038c30..b44c9e7e 100644
--- a/src/pages/dashboard.jsx
+++ b/src/pages/dashboard.jsx
@@ -4,16 +4,25 @@ import { StandardNav } from '@/components/StandardNav';
import { DashboardHeader } from '@/components/dashboard/DashboardHeader';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useEffect, useState } from 'react';
-import { ArrowLeftIcon, CheckCircleIcon, XCircleIcon, ClockIcon } from '@heroicons/react/24/solid';
+import {
+ ArrowLeftIcon,
+ CheckCircleIcon,
+ XCircleIcon,
+ ClockIcon,
+} from '@heroicons/react/24/solid';
import request from '@/utils/request';
import ChallengeCard from '@/components/profile/ChallengeCard';
-import { BoltIcon, RocketLaunchIcon, TrophyIcon } from '@heroicons/react/20/solid';
+import {
+ BoltIcon,
+ RocketLaunchIcon,
+ TrophyIcon,
+} from '@heroicons/react/20/solid';
import Skeleton from 'react-loading-skeleton';
import Upgrade from '@/components/nav/Upgrade';
import { useRouter } from 'next/router';
import { CheckIcon } from '@heroicons/react/20/solid';
-import { Dialog, Transition } from '@headlessui/react'
-import { Fragment } from 'react'
+import { Dialog, Transition } from '@headlessui/react';
+import { Fragment } from 'react';
import OnboardingModal from '@/components/modals/OnboardingModal';
import { UserCircleIcon } from '@heroicons/react/24/solid';
import timeTracker from '@/utils/timeTracker';
@@ -24,11 +33,9 @@ const includedFeatures = [
'Machines with GUI',
'Access to more operating systems',
'Longer machine times',
- 'CTFGuide Pro flair on your profile, comments, and created content'
-
-]
+ 'CTFGuide Pro flair on your profile, comments, and created content',
+];
export default function Dashboard() {
-
const [likes, setLikes] = useState(null);
const [badges, setbadges] = useState([]);
const [challenges, setchallenges] = useState([]);
@@ -42,16 +49,169 @@ export default function Dashboard() {
const exampleObjectives = [
{
completed: false,
- description: "Touch grass",
+ description: 'Touch grass',
},
{
completed: true,
- description: "Eat McDonalds",
+ description: 'Eat McDonalds',
},
- ]
+ ];
const [isOnboardingOpen, setIsOnboardingOpen] = useState(false);
const [completedTasks, setCompletedTasks] = useState(null);
const [timeProgress, setTimeProgress] = useState(null);
+ const [lastNotificationCheck, setLastNotificationCheck] = useState(null);
+ const [processedWarningIds, setProcessedWarningIds] = useState(() => {
+ // Load processed warnings from localStorage on component mount
+ if (typeof window !== 'undefined') {
+ const stored = localStorage.getItem('processedWarningIds');
+ return stored ? new Set(JSON.parse(stored)) : new Set();
+ }
+ return new Set();
+ });
+ const [isCheckingNotifications, setIsCheckingNotifications] = useState(false);
+
+ // Function to check for new notifications and show alerts
+ const checkForNewNotifications = async () => {
+ // Prevent multiple simultaneous checks
+ if (isCheckingNotifications) {
+ console.log('Notification check already in progress, skipping...');
+ return;
+ }
+
+ setIsCheckingNotifications(true);
+
+ try {
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/account/notifications`,
+ 'GET'
+ );
+ if (response && response.length > 0) {
+ // Check for new warning notifications that haven't been processed
+ const newWarnings = response.filter(
+ (notification) =>
+ notification.message &&
+ notification.message.includes('warning') &&
+ !processedWarningIds.has(notification.id)
+ );
+
+ // Only show toast for the most recent new warning that's within the last 5 minutes
+ if (newWarnings.length > 0) {
+ const latestNewWarning = newWarnings[0];
+ const warningTime = new Date(latestNewWarning.createdAt);
+ const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago
+
+ // Only show toast if the warning is recent (within last 5 minutes)
+ if (warningTime > fiveMinutesAgo) {
+ // Mark this notification as processed BEFORE showing toast
+ const newProcessedIds = new Set([
+ ...processedWarningIds,
+ latestNewWarning.id,
+ ]);
+ setProcessedWarningIds(newProcessedIds);
+
+ // Save to localStorage immediately
+ if (typeof window !== 'undefined') {
+ localStorage.setItem(
+ 'processedWarningIds',
+ JSON.stringify([...newProcessedIds])
+ );
+ }
+
+ // Show custom notification for warning (only once for recent warnings)
+ showCustomNotification(latestNewWarning.message, 8000);
+
+ setLastNotificationCheck(new Date(latestNewWarning.createdAt));
+
+ console.log(`Toast shown for warning ID: ${latestNewWarning.id}`);
+ } else {
+ // For older warnings, just mark them as processed without showing toast
+ const newProcessedIds = new Set([
+ ...processedWarningIds,
+ latestNewWarning.id,
+ ]);
+ setProcessedWarningIds(newProcessedIds);
+
+ // Save to localStorage
+ if (typeof window !== 'undefined') {
+ localStorage.setItem(
+ 'processedWarningIds',
+ JSON.stringify([...newProcessedIds])
+ );
+ }
+
+ console.log(
+ `Older warning marked as processed (no toast): ${latestNewWarning.id}`
+ );
+ }
+ } else {
+ console.log('No new warnings found');
+ }
+ }
+ } catch (error) {
+ console.error('Failed to check notifications:', error);
+ } finally {
+ setIsCheckingNotifications(false);
+ }
+ };
+
+ // Function to cleanup old processed warnings (keep only last 100)
+ const cleanupProcessedWarnings = () => {
+ if (typeof window !== 'undefined' && processedWarningIds.size > 100) {
+ const warningArray = Array.from(processedWarningIds);
+ const recentWarnings = warningArray.slice(-100); // Keep only last 100
+ const newProcessedIds = new Set(recentWarnings);
+ setProcessedWarningIds(newProcessedIds);
+ localStorage.setItem(
+ 'processedWarningIds',
+ JSON.stringify([...newProcessedIds])
+ );
+ }
+ };
+
+ // Listen for warning events from other components
+ useEffect(() => {
+ let debounceTimer = null;
+
+ const handleWarningIssued = (event) => {
+ // Clear any existing timer
+ if (debounceTimer) {
+ clearTimeout(debounceTimer);
+ }
+
+ // Set a new timer to debounce the event
+ debounceTimer = setTimeout(() => {
+ console.log('Warning issued event received, checking notifications...');
+ checkForNewNotifications();
+ }, 1000); // Small delay to ensure backend has processed the warning
+ };
+
+ // Add event listener for warning issued events
+ window.addEventListener('warningIssued', handleWarningIssued);
+
+ // Add manual trigger function for testing (accessible from console)
+ window.triggerNotificationCheck = () => {
+ console.log('Manual notification check triggered');
+ checkForNewNotifications();
+ };
+
+ // Add function to clear processed warnings for testing
+ window.clearProcessedWarnings = () => {
+ console.log('Clearing processed warnings...');
+ setProcessedWarningIds(new Set());
+ if (typeof window !== 'undefined') {
+ localStorage.removeItem('processedWarningIds');
+ }
+ };
+
+ return () => {
+ window.removeEventListener('warningIssued', handleWarningIssued);
+ delete window.triggerNotificationCheck;
+ delete window.clearProcessedWarnings;
+ if (debounceTimer) {
+ clearTimeout(debounceTimer);
+ }
+ };
+ }, [processedWarningIds]);
useEffect(() => {
const user = localStorage.getItem('username');
@@ -63,28 +223,38 @@ export default function Dashboard() {
);
const data = await response.json();
setbadges(data);
- } catch { }
+ } catch {}
};
fetchBadges();
setbadges([]);
const fetchChallenges = async () => {
try {
- const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes';
- const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null);
+ const pinnedChallengeEndPoint =
+ process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes';
+ const pinnedChallengeResult = await request(
+ pinnedChallengeEndPoint,
+ 'GET',
+ null
+ );
setchallenges(pinnedChallengeResult);
- } catch (error) { }
+ } catch (error) {}
};
fetchChallenges();
setchallenges([]);
const fetchData = async () => {
try {
- const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes';
- const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null);
+ const pinnedChallengeEndPoint =
+ process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes';
+ const pinnedChallengeResult = await request(
+ pinnedChallengeEndPoint,
+ 'GET',
+ null
+ );
// setLikes(pinnedChallengeResult);
} catch (error) {
- console.error("Failed to fetch pinnedChallengeResults: ", error)
+ console.error('Failed to fetch pinnedChallengeResults: ', error);
}
};
fetchData();
@@ -95,13 +265,17 @@ export default function Dashboard() {
} catch (error) {
console.error('Failed to fetch objectives: ', error);
}
- }
+ };
fetchObjectives();
const fetchRecommendedChallenges = async () => {
setLoading(true);
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/challenges/dash/recommended`, 'GET', null);
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/challenges/dash/recommended`,
+ 'GET',
+ null
+ );
setLikes(response); // Assuming the response directly contains the array of challenges
} catch (error) {
console.error('Failed to fetch recommended challenges: ', error);
@@ -110,11 +284,14 @@ export default function Dashboard() {
}
};
-
const fetchPopularChallenges = async () => {
setLoading(true);
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/challenges/dash/popular`, 'GET', null);
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/challenges/dash/popular`,
+ 'GET',
+ null
+ );
setPopular(response); // Assuming the response directly contains the array of challenges
} catch (error) {
console.error('Failed to fetch recommended challenges: ', error);
@@ -123,20 +300,23 @@ export default function Dashboard() {
}
};
- const fetchAccountDetails = async() => {
+ const fetchAccountDetails = async () => {
request(`${process.env.NEXT_PUBLIC_API_URL}/account`, 'GET', null)
.then((data) => {
-
setRole(data.role);
})
.catch((err) => {
console.log(err);
});
- }
+ };
const checkCompletedTasks = async () => {
try {
- const accountResponse = await request(`${process.env.NEXT_PUBLIC_API_URL}/account`, 'GET', null);
+ const accountResponse = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/account`,
+ 'GET',
+ null
+ );
const hasProfilePicture = accountResponse.profileImage;
const hasCompletedChallenge = accountResponse.points > 0;
@@ -154,34 +334,55 @@ export default function Dashboard() {
fetchRecommendedChallenges();
fetchPopularChallenges();
fetchAccountDetails();
- request(`${process.env.NEXT_PUBLIC_API_URL}/activityFeed/`, 'GET', null).then(response => {
- console.log(response)
+
+ // Check for recent notifications immediately (within last 5 minutes)
+ setTimeout(() => {
+ checkForNewNotifications();
+ }, 1000); // Check after 1 second to ensure component is fully loaded
+
+ // Cleanup old processed warnings on initial load
+ cleanupProcessedWarnings();
+
+ request(`${process.env.NEXT_PUBLIC_API_URL}/activityFeed/`, 'GET', null)
+ .then((response) => {
+ console.log(response);
setActivities(response.activityFeed);
})
- .catch(error => {
+ .catch((error) => {
console.error('Error fetching feed data: ', error);
});
const intervalId = setInterval(() => {
- request(`${process.env.NEXT_PUBLIC_API_URL}/activityFeed/`, 'GET', null).then(response => {
+ request(`${process.env.NEXT_PUBLIC_API_URL}/activityFeed/`, 'GET', null)
+ .then((response) => {
//console.log(response)
if (response.activityFeed.length > 0) {
setActivities(response.activityFeed);
}
})
- .catch(error => {
+ .catch((error) => {
console.error('Error fetching feed data: ', error);
});
}, 5000); // 5000 milliseconds = 5 seconds
- return () => clearInterval(intervalId); //
-
+ // Cleanup old processed warnings every 5 minutes
+ const cleanupIntervalId = setInterval(() => {
+ cleanupProcessedWarnings();
+ }, 300000); // 5 minutes
+
+ return () => {
+ clearInterval(intervalId);
+ clearInterval(cleanupIntervalId);
+ };
}, []);
useEffect(() => {
// Check onboarding status from API
const checkOnboardingStatus = async () => {
try {
- const response = await request(`${process.env.NEXT_PUBLIC_API_URL}/account`, 'GET');
+ const response = await request(
+ `${process.env.NEXT_PUBLIC_API_URL}/account`,
+ 'GET'
+ );
if (!response.hasCompletedOnboarding) {
setIsOnboardingOpen(true);
}
@@ -191,6 +392,8 @@ export default function Dashboard() {
};
checkOnboardingStatus();
+
+ // Don't check for notifications on initial load to prevent showing old notifications on refresh
}, []);
const handleHideOnboarding = () => {
@@ -231,77 +434,103 @@ export default function Dashboard() {
-
-
-
+
-
-
- {completedTasks && (!completedTasks.profilePicture || !completedTasks.firstChallenge) && (
-
-
-
+
+
+ {completedTasks &&
+ (!completedTasks.profilePicture ||
+ !completedTasks.firstChallenge) && (
+
+
+
Onboarding Tasks
Hide
-
Looks like you're new around here. You should try to complete these tasks. Or don't.
-
-
{
- window.location.href = "./settings"
- }} className={`${completedTasks.profilePicture ? 'bg-green-900/20 border border-green-800' : 'bg-neutral-700/50 hover:bg-neutral-700/70 border border-neutral-600'} transition-colors p-6 rounded-lg cursor-pointer`}>
-
-
-
+
+ Looks like you're new around here. You should try to
+ complete these tasks. Or don't.
+
+
+
{
+ window.location.href = './settings';
+ }}
+ className={`${
+ completedTasks.profilePicture
+ ? 'border border-green-800 bg-green-900/20'
+ : 'border border-neutral-600 bg-neutral-700/50 hover:bg-neutral-700/70'
+ } cursor-pointer rounded-lg p-6 transition-colors`}
+ >
+
+
+
+
+
+ Set a profile picture
+
+ {completedTasks.profilePicture && (
+
+ )}
+
+
+ Personalize your account by adding a profile picture
+
-
Set a profile picture
- {completedTasks.profilePicture && (
-
+
{
+ window.location.href =
+ './challenges/07671f2f-cd67-4f0f-a3d1-9bdea299c59c?onboarding=true';
+ }}
+ className={`${
+ completedTasks.firstChallenge
+ ? 'border border-green-800 bg-green-900/20'
+ : 'border border-neutral-600 bg-neutral-700/50 hover:bg-neutral-700/70'
+ } cursor-pointer rounded-lg p-6 transition-colors`}
+ >
+
+
+
+
+
+ Complete your first challenge
+
+ {completedTasks.firstChallenge && (
+
)}
-
Personalize your account by adding a profile picture
-
-
{
- window.location.href = "./challenges/07671f2f-cd67-4f0f-a3d1-9bdea299c59c?onboarding=true"
- }} className={`${completedTasks.firstChallenge ? 'bg-green-900/20 border border-green-800' : 'bg-neutral-700/50 hover:bg-neutral-700/70 border border-neutral-600'} transition-colors p-6 rounded-lg cursor-pointer`}>
-
-
-
+
+ Try solving an entry-level cybersecurity challenge
+
-
Complete your first challenge
- {completedTasks.firstChallenge && (
-
- )}
-
-
Try solving an entry-level cybersecurity challenge
-
)}
-
+
{/* Add after the onboarding tasks section */}
{timeProgress && (
-
-
+
+
Weekly Progress
-
+
beta
-
+
This is an experimental feature.
window.location.href = '/report'}
- className="text-blue-400 hover:text-blue-300 text-left"
+ onClick={() => (window.location.href = '/report')}
+ className="text-left text-blue-400 hover:text-blue-300"
>
Click here to report an issue →
@@ -310,162 +539,246 @@ export default function Dashboard() {
-
+
{/* Progress Bar */}
-
+
{/* Stats */}
-
-
-
Time Spent
-
- {Math.round(timeProgress.totalMinutesSpent / 60)}h {timeProgress.totalMinutesSpent % 60}m
+
+
+
Time Spent
+
+ {Math.round(timeProgress.totalMinutesSpent / 60)}h{' '}
+ {timeProgress.totalMinutesSpent % 60}m
-
-
Weekly Goal
-
+
+
Weekly Goal
+
{Math.round(timeProgress.weeklyGoalMinutes / 60)}h
-
-
Days Left
-
+
+
Days Left
+
{timeProgress.daysLeft} days
{/* Status Message */}
-
-
+
+
{timeProgress.onTrack
- ? `You're on track! ${Math.round(timeProgress.progressPercentage)}% of your weekly goal complete.`
- : `You're behind schedule. ${Math.round(timeProgress.progressPercentage)}% complete with ${timeProgress.daysLeft} days left.`
- }
+ ? `You're on track! ${Math.round(
+ timeProgress.progressPercentage
+ )}% of your weekly goal complete.`
+ : `You're behind schedule. ${Math.round(
+ timeProgress.progressPercentage
+ )}% complete with ${
+ timeProgress.daysLeft
+ } days left.`}
)}
-
Recommended Challenges
-
- {loading ? <>
> : (
- likes?.length > 0 ?
- likes.map((challenge, index) =>
)
- : <>
>
+
+ Recommended Challenges
+
+
+ {loading ? (
+ <>
+
+
+ >
+ ) : likes?.length > 0 ? (
+ likes.map((challenge, index) => (
+
+ ))
+ ) : (
+ <>
+
+
+ >
)}
-
-
-
Popular Challenges
-
- {loading ? <>
> : (
- popular?.length > 0 ?
- popular.map((challenge, index) =>
)
- : <>
>
+
+
+
+ Popular Challenges
+
+
+ {loading ? (
+ <>
+
+
+ >
+ ) : popular?.length > 0 ? (
+ popular.map((challenge, index) => (
+
+ ))
+ ) : (
+ <>
+
+
+ >
)}
-
-
-
-
-
+
+
-
-
+
+
Global Feed
-
-
- {activities && activities.length > 0 ?
- activities.slice().reverse().map((data) =>
+
+ {activities && activities.length > 0 ? (
+ activities
+ .slice()
+ .reverse()
+ .map((data) => (
- ) :
+ ))
+ ) : (
<>
-
+
>
-}
-
-
-
+ )}
-
-
- { role == "USER" &&
-
-
+
+ {role == 'USER' && (
+
+
Sponsor Messaging
setShowUpgradeModal(true)}
>
-
-
-
Upgrade to CTFGuide Pro today for just $5/month .
+
+
+
+ Upgrade to CTFGuide Pro today for just{' '}
+ $5/month .
+
-
-}
-
- {showUpgradeModal &&
-
-
-
+ {showUpgradeModal && (
+
+
+
+
-
Upgrade to CTFGuide Pro
-
+
+ Upgrade to CTFGuide{' '}
+ Pro
+
-
+
-
Monthly Subscription
+
+ Monthly Subscription
+
- Enjoy our core features for free and upgrade to get perks like priority access to terminals, custom container images, customization perks, and more!
-
+ Enjoy our core features for free and upgrade to get perks
+ like priority access to terminals, custom container
+ images, customization perks, and more!
-
What's included
+
+ What's included
+
{includedFeatures.map((feature) => (
-
+
{feature}
))}
-
setShowUpgradeModal(false)} className=" mt-6 px-4 py-1 bg-neutral-900 hover:bg-neutral-700 text-white">
+ setShowUpgradeModal(false)}
+ className=" mt-6 bg-neutral-900 px-4 py-1 text-white hover:bg-neutral-700"
+ >
No, thanks.
-
-
-
-
-
-
-
}
-
+ )}
+
>
);
}
diff --git a/src/pages/login.jsx b/src/pages/login.jsx
index e2808958..e26117f8 100644
--- a/src/pages/login.jsx
+++ b/src/pages/login.jsx
@@ -9,6 +9,7 @@ import 'react-toastify/dist/ReactToastify.css';
import AuthFooter from '@/components/auth/AuthFooter';
import { GoogleLogin } from '@react-oauth/google';
import { jwtDecode } from 'jwt-decode';
+import AccountReactivation from '@/components/AccountReactivation';
import { Context } from '@/context';
import { useContext } from 'react';
@@ -21,15 +22,17 @@ export default function Login() {
const [password, setPassword] = useState('');
const [accountType, setAccountType] = useState('EMAIL'); // ['EMAIL', 'GOOGLE']
const [showOnboarding, setShowOnboarding] = useState(false);
+ const [accountSuspended, setAccountSuspended] = useState(false);
+ const [suspendedAccountData, setSuspendedAccountData] = useState(null);
async function handleLoginRequest(requestOptions, isGoogle) {
setIsLoading(true);
-
+
try {
const url = process.env.NEXT_PUBLIC_API_URL + '/account/login';
const response = await fetch(url, requestOptions);
- if(response.status === 404) {
- if(isGoogle) {
+ if (response.status === 404) {
+ if (isGoogle) {
setShowOnboarding(true);
return;
}
@@ -51,13 +54,30 @@ export default function Login() {
router.push('/dashboard');
} else {
- if(data.status === 500) {
- toast.error("There was a problem logging in, try again later");
+ // Check if account is suspended
+ if (data.code === 'ACCOUNT_SUSPENDED') {
+ setAccountSuspended(true);
+
+ // Use deletion info directly from login response
+ const deletionInfo = data.deletionInfo || null;
+
+ setSuspendedAccountData({
+ email: data.email || email,
+ message: data.message,
+ accountType: accountType,
+ password: accountType === 'EMAIL' ? password : null,
+ deletionInfo: deletionInfo, // Pass deletion info to reactivation component
+ });
+ return;
+ }
+
+ if (data.status === 500) {
+ toast.error('There was a problem logging in, try again later');
} else {
toast.error(data.message);
}
}
- } catch(error) {
+ } catch (error) {
console.log(error);
}
setIsLoading(false);
@@ -65,24 +85,24 @@ export default function Login() {
const handleLogin = async (e) => {
e.preventDefault();
- const requestOptions = {
- method: 'POST',
- body: JSON.stringify({ email, password, accountType: 'EMAIL'}),
- headers: { 'Content-Type': 'application/json' }
+ const requestOptions = {
+ method: 'POST',
+ body: JSON.stringify({ email, password, accountType: 'EMAIL' }),
+ headers: { 'Content-Type': 'application/json' },
};
setAccountType('EMAIL');
await handleLoginRequest(requestOptions, false);
- }
+ };
async function handleSuccess(data) {
const { credential } = data;
const decode = jwtDecode(credential);
const { email } = decode;
setEmail(email);
- const requestOptions = {
- method: 'POST',
- body: JSON.stringify({ email, password: null, accountType: 'GOOGLE'}),
- headers: { 'Content-Type': 'application/json' }
+ const requestOptions = {
+ method: 'POST',
+ body: JSON.stringify({ email, password: null, accountType: 'GOOGLE' }),
+ headers: { 'Content-Type': 'application/json' },
};
setAccountType('GOOGLE');
await handleLoginRequest(requestOptions, true);
@@ -93,8 +113,51 @@ export default function Login() {
toast.error('Google login failed. Please try again later.');
}
-
- if(showOnboarding) return
+ const handleReactivated = (token) => {
+ if (token) {
+ // Account was reactivated successfully
+ document.cookie = `idToken=${token}; SameSite=None; Secure; Path=/`;
+ router.push('/dashboard');
+ } else {
+ // Go back to login form
+ setAccountSuspended(false);
+ setSuspendedAccountData(null);
+ }
+ };
+
+ const handleCancelReactivation = () => {
+ setAccountSuspended(false);
+ setSuspendedAccountData(null);
+ };
+
+ if (showOnboarding)
+ return (
+
+ );
+
+ if (accountSuspended) {
+ return (
+ <>
+
+
Account Suspended - CTFGuide
+
+
+ >
+ );
+ }
return (
<>
@@ -105,30 +168,24 @@ export default function Login() {
url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
-