From fd3cdc69add45f213ffa846069fc3def2a46a3a0 Mon Sep 17 00:00:00 2001 From: vkuchenik Date: Thu, 4 Jun 2026 15:30:01 -0700 Subject: [PATCH] some routes added --- client/jsconfig.json | 3 +- client/package-lock.json | 740 +++--------------- client/package.json | 4 +- client/src/App.jsx | 53 +- client/src/Login.jsx | 91 +++ .../CanvasComponents/AlertLevelWidget.jsx | 4 +- .../CanvasComponents/CustomResizeHandle.jsx | 4 +- .../CanvasComponents/FirstWidgetButton.jsx | 78 +- .../CanvasComponents/MapSettingsButton.jsx | 9 +- .../Canvas/CanvasComponents/SearchBar.jsx | 4 +- .../CanvasComponents/SettingsButton.jsx | 8 +- .../Canvas/CanvasComponents/Tooltip.jsx | 34 +- .../Canvas/CanvasComponents/Widget.jsx | 35 +- client/src/components/Canvas/views/Home.jsx | 99 ++- .../Canvas/views/HomeTabs/MyDashboard.jsx | 66 +- client/src/components/Header/Header.jsx | 16 +- .../src/components/Header/UserAvatarMenu.jsx | 7 +- client/src/components/Sidebar/Sidebar.jsx | 101 +-- client/src/components/ui/color-mode.jsx | 5 +- client/src/components/ui/password-input.jsx | 122 +++ client/src/components/ui/provider.jsx | 4 +- client/src/main.jsx | 16 +- client/src/theme.js | 1 + client/vite.config.js | 6 +- 24 files changed, 636 insertions(+), 874 deletions(-) create mode 100644 client/src/Login.jsx create mode 100644 client/src/components/ui/password-input.jsx diff --git a/client/jsconfig.json b/client/jsconfig.json index c205775..1542a85 100644 --- a/client/jsconfig.json +++ b/client/jsconfig.json @@ -6,6 +6,7 @@ "skipLibCheck": true, "paths": { "@/*": ["./src/*"] - } + }, + "jsx": "react" } } \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 794430d..8497895 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,6 @@ "@chakra-ui/react": "^3.22.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@tailwindcss/vite": "^4.1.11", "framer-motion": "^12.23.0", "leaflet": "^1.9.4", "lucide-react": "^0.539.0", @@ -20,10 +19,9 @@ "react-dom": "^19.1.0", "react-grid-layout": "^1.5.2", "react-hook-form": "^7.62.0", - "react-icons": "^5.5.0", "react-leaflet": "^5.0.0", "react-resizable": "^3.0.5", - "tailwindcss": "^4.1.11", + "react-router-dom": "^7.16.0", "uuid": "^11.1.0" }, "devDependencies": { @@ -39,18 +37,6 @@ "vite-jsconfig-paths": "^2.0.1" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@ark-ui/react": { "version": "5.16.1", "resolved": "https://registry.npmjs.org/@ark-ui/react/-/react-5.16.1.tgz", @@ -414,6 +400,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "aix" @@ -429,6 +416,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "android" @@ -444,6 +432,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -459,6 +448,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "android" @@ -474,6 +464,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -489,6 +480,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -504,6 +496,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -519,6 +512,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -534,6 +528,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -549,6 +544,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -564,6 +560,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "linux" @@ -579,6 +576,7 @@ "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -594,6 +592,7 @@ "cpu": [ "mips64el" ], + "dev": true, "optional": true, "os": [ "linux" @@ -609,6 +608,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -624,6 +624,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -639,6 +640,7 @@ "cpu": [ "s390x" ], + "dev": true, "optional": true, "os": [ "linux" @@ -654,6 +656,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -669,6 +672,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "netbsd" @@ -684,6 +688,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "netbsd" @@ -699,6 +704,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "openbsd" @@ -714,6 +720,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "openbsd" @@ -729,6 +736,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "sunos" @@ -744,6 +752,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -759,6 +768,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -774,6 +784,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1053,17 +1064,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", @@ -1134,6 +1134,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "android" @@ -1146,6 +1147,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -1158,6 +1160,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -1170,6 +1173,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -1182,6 +1186,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -1194,6 +1199,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -1206,6 +1212,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1218,6 +1225,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1230,6 +1238,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1242,6 +1251,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1254,6 +1264,7 @@ "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1266,6 +1277,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1278,6 +1290,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1290,6 +1303,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1302,6 +1316,7 @@ "cpu": [ "s390x" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1314,6 +1329,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1326,6 +1342,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1338,6 +1355,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1350,6 +1368,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1362,6 +1381,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1588,257 +1608,11 @@ "@swc/counter": "^0.1.3" } }, - "node_modules/@tailwindcss/node": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", - "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "enhanced-resolve": "^5.18.1", - "jiti": "^2.4.2", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", - "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", - "hasInstallScript": true, - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-arm64": "4.1.11", - "@tailwindcss/oxide-darwin-x64": "4.1.11", - "@tailwindcss/oxide-freebsd-x64": "4.1.11", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", - "@tailwindcss/oxide-linux-x64-musl": "4.1.11", - "@tailwindcss/oxide-wasm32-wasi": "4.1.11", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", - "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", - "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", - "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", - "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", - "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", - "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", - "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", - "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", - "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", - "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@emnapi/wasi-threads": "^1.0.2", - "@napi-rs/wasm-runtime": "^0.2.11", - "@tybys/wasm-util": "^0.9.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", - "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", - "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", - "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", - "dependencies": { - "@tailwindcss/node": "4.1.11", - "@tailwindcss/oxide": "4.1.11", - "tailwindcss": "4.1.11" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -2785,14 +2559,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "engines": { - "node": ">=18" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2840,6 +2606,19 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -2904,14 +2683,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "engines": { - "node": ">=8" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2924,18 +2695,6 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "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==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2948,6 +2707,7 @@ "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -3195,6 +2955,7 @@ "version": "6.4.6", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -3302,6 +3063,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3399,11 +3161,6 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, - "node_modules/graceful-fs": { - "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==" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3535,14 +3292,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3634,223 +3383,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3904,14 +3436,6 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3937,35 +3461,11 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/motion-dom": { "version": "12.22.0", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.22.0.tgz", @@ -3999,6 +3499,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { "type": "github", @@ -4177,6 +3678,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, "engines": { "node": ">=12" }, @@ -4197,6 +3699,7 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -4329,15 +3832,6 @@ "react": "^16.8.0 || ^17 || ^18 || ^19" } }, - "node_modules/react-icons": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", - "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", - "license": "MIT", - "peerDependencies": { - "react": "*" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -4370,6 +3864,44 @@ "react": ">= 16.3" } }, + "node_modules/react-router": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.16.0.tgz", + "integrity": "sha512-wArC8lVyJb3+jM9OpDyW6hLCizACWkvQR/sSGqSs+o5uEXEtGlqdZ4v8hENR3Jad6i+LRkK93q/+bQAcvl6V1A==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.16.0.tgz", + "integrity": "sha512-kMUAbimWB5FVbF4Bce4bJsiKJWLIUHq/mEG8+CFDnCSgltptBiG5nguducmsJeGKytlCvQud9Qhzpn49iduTlA==", + "license": "MIT", + "dependencies": { + "react-router": "7.16.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/recrawl-sync": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recrawl-sync/-/recrawl-sync-2.2.3.tgz", @@ -4426,6 +3958,7 @@ "version": "4.44.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "dev": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -4465,6 +3998,12 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4519,6 +4058,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4690,35 +4230,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tailwindcss": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", - "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==" - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -4744,6 +4255,7 @@ "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" @@ -4821,6 +4333,7 @@ "version": "6.3.5", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "dev": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -5017,27 +4530,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "engines": { - "node": ">=18" - } - }, - "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/client/package.json b/client/package.json index 5185486..df9ea57 100644 --- a/client/package.json +++ b/client/package.json @@ -13,7 +13,6 @@ "@chakra-ui/react": "^3.22.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@tailwindcss/vite": "^4.1.11", "framer-motion": "^12.23.0", "leaflet": "^1.9.4", "lucide-react": "^0.539.0", @@ -22,10 +21,9 @@ "react-dom": "^19.1.0", "react-grid-layout": "^1.5.2", "react-hook-form": "^7.62.0", - "react-icons": "^5.5.0", "react-leaflet": "^5.0.0", "react-resizable": "^3.0.5", - "tailwindcss": "^4.1.11", + "react-router-dom": "^7.16.0", "uuid": "^11.1.0" }, "devDependencies": { diff --git a/client/src/App.jsx b/client/src/App.jsx index af7991e..a19dcd0 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,10 +1,59 @@ -import Dashboard from './components/Dashboard.jsx' import 'leaflet/dist/leaflet.css'; +import { Routes, Route } from 'react-router-dom'; +import { useRecipe, Grid, GridItem, useDialog } from "@chakra-ui/react"; +import { createContext } from "react"; +import Login from "@/Login.jsx"; +import Sidebar from "./components/Sidebar/Sidebar.jsx"; +import DialogPopup from "@/components/Canvas/CanvasComponents/DialogPopup.jsx"; +import Header from "@/components/Header/Header.jsx"; +import Home from "./components/Canvas/views/Home.jsx"; +import RegionalMap from "./components/Canvas/views/RegionalMap.jsx"; +import Volcano from "@/components/Canvas/views/Volcano.jsx"; +function AppFoundation({children}) { + const recipe = useRecipe({ key: "dashboard" }); + const styles = recipe(); + const dialog = useDialog(); + + return ( + <> + + + +
+ + + + + + {children} + + + + ) +} + +// function ProtectedRoute({ user, children }) { +// if (user) return children; +// else return ; +// } function App() { + const sidebarContext = createContext(["Home", "Global Map", "Regional Map", "Volcano", "Admin"]); + // const [user, setUser] = useState(null); + return ( - + + } /> + } /> + } /> + } /> + ); } diff --git a/client/src/Login.jsx b/client/src/Login.jsx new file mode 100644 index 0000000..6f71d4c --- /dev/null +++ b/client/src/Login.jsx @@ -0,0 +1,91 @@ +import { useContext } from 'react'; +import { useForm } from 'react-hook-form'; +import { + Button, + Field, + Input, + Stack, + useRecipe, + Center, + Text, + Flex, + Heading, + Highlight, + GridItem, + Grid +} from "@chakra-ui/react" +import { PasswordInput } from "@/components/ui/password-input.jsx"; + +export default function Login( signedIn, setSignedIn) { + const recipe = useRecipe({ key: "dashboard" }); // styling recipes option + const styles = recipe(); // use style + + const { + register, + handleSubmit, + formState: { errors, isSubmitSuccessful }, + } = useForm({ + defaultValues: { + username: "", + password: "", + } + }); + + const onSubmit = (data) => { + console.log(data); + // setUser(data.username); + }; + + return ( + + + + + + + VDAP + + + + + + +
+
+ + Sign In + + + {errors.username?.message} + + + + + {errors.password?.message} + + + + +
+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/client/src/components/Canvas/CanvasComponents/AlertLevelWidget.jsx b/client/src/components/Canvas/CanvasComponents/AlertLevelWidget.jsx index 4f7fd2c..c976876 100644 --- a/client/src/components/Canvas/CanvasComponents/AlertLevelWidget.jsx +++ b/client/src/components/Canvas/CanvasComponents/AlertLevelWidget.jsx @@ -2,7 +2,7 @@ import Widget from "./Widget"; import { Stack, Box, Field, Input, Button, Text, Flex } from "@chakra-ui/react"; import { useForm } from "react-hook-form"; import { useState } from "react"; -import { LuAsterisk } from "react-icons/lu"; +import { Asterisk } from 'lucide-react'; export default function AlertLevel({id, isEditable, isDelete, DeleteWidget}) { const { register, handleSubmit, reset, formState: {errors} } = useForm(); @@ -44,7 +44,7 @@ export default function AlertLevel({id, isEditable, isDelete, DeleteWidget}) { - Volcano Name + Volcano Name { @@ -19,7 +19,7 @@ const CustomResizeHandle = React.forwardRef((props, ref) => { zIndex: "1", }} > - + ); }); diff --git a/client/src/components/Canvas/CanvasComponents/FirstWidgetButton.jsx b/client/src/components/Canvas/CanvasComponents/FirstWidgetButton.jsx index 83c7c9e..53816a5 100644 --- a/client/src/components/Canvas/CanvasComponents/FirstWidgetButton.jsx +++ b/client/src/components/Canvas/CanvasComponents/FirstWidgetButton.jsx @@ -1,36 +1,58 @@ import { Box, Menu, Portal } from '@chakra-ui/react' import WidgetMenu from './WidgetMenu'; +import AlertLevel from "@/components/Canvas/CanvasComponents/AlertLevelWidget.jsx"; export default function FirstWidgetButton({ appendWidget }) { - const triggerItem = (<> - - - Add Your First Widget - - - ); + const triggerItem = ( + <> + + + Add Your First Widget + + + + ); const positioning = { placement: "bottom-middle" }; - const WidgetMenuProps = { appendWidget, triggerItem, positioning }; + // const WidgetMenuProps = { appendWidget, triggerItem, positioning }; return ( - + // + + {triggerItem} + + + + appendWidget(AlertLevel, 4, 7, 4, 7, 8, 14)} // width and height are passed through here for each widget + > + Alert Level + + CO2 + IVANS + Plume Heights + Alert Level Changes + + + + ); } \ No newline at end of file diff --git a/client/src/components/Canvas/CanvasComponents/MapSettingsButton.jsx b/client/src/components/Canvas/CanvasComponents/MapSettingsButton.jsx index 0011f88..1cb87e3 100644 --- a/client/src/components/Canvas/CanvasComponents/MapSettingsButton.jsx +++ b/client/src/components/Canvas/CanvasComponents/MapSettingsButton.jsx @@ -1,8 +1,7 @@ import { Box, Checkbox, Separator , CloseButton, Text, chakra, Field, IconButton, Icon, Input, Fieldset, Flex } from "@chakra-ui/react"; import { useState } from "react"; -import { FiSettings } from "react-icons/fi"; -import { IoIosArrowDown } from "react-icons/io"; -import { IoIosArrowUp } from "react-icons/io"; +import { ChevronDown } from 'lucide-react'; +import { ChevronUp } from 'lucide-react'; export default function MapSettingsButton() { const [open, setOpen] = useState(false); @@ -16,7 +15,7 @@ export default function MapSettingsButton() { ):( setOpen(true)}> - + ); } @@ -57,7 +56,7 @@ function Lightning() { Lightning setOpen(!open)}> - {open ? ():()} + {open ? ():()} {open && ()} diff --git a/client/src/components/Canvas/CanvasComponents/SearchBar.jsx b/client/src/components/Canvas/CanvasComponents/SearchBar.jsx index 5d116a4..8c4c3e9 100644 --- a/client/src/components/Canvas/CanvasComponents/SearchBar.jsx +++ b/client/src/components/Canvas/CanvasComponents/SearchBar.jsx @@ -1,9 +1,9 @@ import { Input, InputGroup } from "@chakra-ui/react"; -import { FiSearch } from "react-icons/fi" +import { Search } from 'lucide-react'; export function SearchBar({ placeholder="Enter a volcano to search", size="sm", width="210px" }) { return ( - }> + }> Add Widget ); + const triggerItem = (<> Add Widget ); const WidgetMenuProps = { appendWidget, triggerItem } return ( - + diff --git a/client/src/components/Canvas/CanvasComponents/Tooltip.jsx b/client/src/components/Canvas/CanvasComponents/Tooltip.jsx index 4c73b74..0037254 100644 --- a/client/src/components/Canvas/CanvasComponents/Tooltip.jsx +++ b/client/src/components/Canvas/CanvasComponents/Tooltip.jsx @@ -1,11 +1,9 @@ import { useState, useRef } from "react"; -import { chakra, useSlotRecipe } from "@chakra-ui/react"; +import { chakra } from "@chakra-ui/react"; export default function Tooltip ({tooltipkey, content, sidebarIsOpen, children}) { const [isVisible, setIsVisible] = useState(false); - const recipe = useSlotRecipe({ key: "sidebar" }); - const styles = recipe(); const timeoutId = useRef(null); return ( @@ -30,22 +28,20 @@ export default function Tooltip ({tooltipkey, content, sidebarIsOpen, children}) > {children} {isVisible && !sidebarIsOpen && ( - <> - - {content} - - + + {content} + )} ) diff --git a/client/src/components/Canvas/CanvasComponents/Widget.jsx b/client/src/components/Canvas/CanvasComponents/Widget.jsx index f9fc0d1..b67ce29 100644 --- a/client/src/components/Canvas/CanvasComponents/Widget.jsx +++ b/client/src/components/Canvas/CanvasComponents/Widget.jsx @@ -1,37 +1,30 @@ import { useSlotRecipe, chakra, Flex, CloseButton, Text, IconButton } from "@chakra-ui/react" -import { GrUndo } from "react-icons/gr"; +import { Undo } from 'lucide-react'; export default function Widget(props) { // deconstructing props const { id, title, isEditable, isDelete, DeleteWidget, isSubmit, setIsSubmit, children } = props; + const recipe = useSlotRecipe({ key: "widget" }); const styles = recipe(); - return ( <> - {isDelete ? ( - <> - - {title} - DeleteWidget(id)} size="xs" _hover={{bg: "tomato", color: "white"}}/> - - - ):( - <> - - {title} - {isSubmit ? ( - setIsSubmit(false)} size="xs" bg="base300" cursor="pointer"> - ):(null)} - - - )} + + {title} + {isDelete ? ( + DeleteWidget(id)} size="xs" _hover={{bg: "tomato", color: "white"}}/> + ):( + isSubmit ? ( + setIsSubmit(false)} size="xs" bg="base300" cursor="pointer"> + ):null + )} + - + {children} - + ); } diff --git a/client/src/components/Canvas/views/Home.jsx b/client/src/components/Canvas/views/Home.jsx index a04309f..b8214b6 100644 --- a/client/src/components/Canvas/views/Home.jsx +++ b/client/src/components/Canvas/views/Home.jsx @@ -1,4 +1,5 @@ import { HStack, Flex, Tabs } from "@chakra-ui/react"; +import { useState } from "react"; import MyDashboard from "./HomeTabs/MyDashboard"; import { SearchBar } from "../CanvasComponents/SearchBar"; import { SettingsButton } from "../CanvasComponents/SettingsButton"; @@ -13,14 +14,17 @@ import { v4 as uuid } from 'uuid'; import { CanvasHeaderTabs } from '../CanvasComponents/CanvasHeaderTabs'; import { DASHBOARD_TABS } from "@/constants/viewKeys"; -export default function Home(props) { - // deconstructing props - const { view, layout, setLayout, setOriginalLayout, onLayoutChange, onChangeView, onCancel, setOriginalWidgets, - isDelete, setIsDelete, beginEditIfNeeded, isEditable, setIsEditable, widgetArray, setWidgetArray } = props; +export default function Home() { + const [isEditable, setIsEditable] = useState(false); // editable=true means static=false (vice versa) + const [isDelete, setIsDelete] = useState(false); + const [originalLayout, setOriginalLayout] = useState([]); + const [originalWidgets, setOriginalWidgets] = useState([]); + const [layout, setLayout] = useState([]); + const [widgetArray, setWidgetArray] = useState([]); + + function appendWidget(name, w, h, min_w, minh, max_w, max_h) { + saveLayoutState(); // Save state before anything else - function appendWidget(name, w, h, minw, minh, maxw, maxh) { - beginEditIfNeeded(); // Save state before anything else - const newID = uuid(); // could be replaced with something else like guid const COLS = 16; const W = w ?? 3; @@ -30,7 +34,7 @@ export default function Home(props) { ...widgetArray, {i: newID, widget: name } ]); - // onAddWidget(newID, w, h, minw, minh, maxw, maxh); // updating array containing info on layout of widgets + // onAddWidget(newID, w, h, min_w, minh, max_w, max_h); // updating array containing info on layout of widgets setLayout(prev => [ ...prev, @@ -40,10 +44,10 @@ export default function Home(props) { y: 0, w: w, h: h, - minW: minw, + minW: min_w, minH: minh, - maxW: maxw, - maxH: maxh, + maxW: max_w, + maxH: max_h, static: false, resizeHandles: ['se'] }, @@ -67,7 +71,7 @@ export default function Home(props) { const onEditWidgets = () => { console.log("Start deleting widgets..."); - beginEditIfNeeded(); // Save state before anything else + saveLayoutState(); // Save state before anything else setLayout(prevLayout => prevLayout.map(item => ({ ...item, @@ -96,39 +100,52 @@ export default function Home(props) { else return; } + + const saveLayoutState = () => { + if ( !isEditable ) { + setOriginalLayout(layout); + setOriginalWidgets(widgetArray); + } + }; + + const onCancel = () => { + console.log("canceling changes..."); + console.log(originalWidgets); + if (originalLayout.length) { + setLayout(originalLayout.map(item => ({ + ...item, + static: true + }))); + } + setWidgetArray(originalWidgets); + setIsEditable(false); + setIsDelete(false); + setOriginalLayout([]); + setOriginalWidgets([]); + } + + const onLayoutChange = (newLayout) => setLayout(newLayout); + + // Prop Forwarding - const MyDashboardProps = { layout, onLayoutChange, isEditable, beginEditIfNeeded, isDelete, DeleteWidget, widgetArray, appendWidget }; + const MyDashboardProps = { layout, onLayoutChange, isEditable, saveLayoutState, isDelete, DeleteWidget, widgetArray, appendWidget }; const settingsButtonProps = { onEditWidgets, appendWidget }; return ( - /* HEADER */ - { - const nextView = e.value; - onChangeView(nextView); - }} - > - - + /* SUB HEADER */ + + + {/* TABS */} + {/* */} {/* TODO: rename to SubHeaderTabs */} + + {DASHBOARD_TABS.map(({ value, label }) => + + { label } + + )} + + + {/* EDIT MODE BUTTONS */} {isEditable ? ( <> diff --git a/client/src/components/Canvas/views/HomeTabs/MyDashboard.jsx b/client/src/components/Canvas/views/HomeTabs/MyDashboard.jsx index 91364e2..a88be56 100644 --- a/client/src/components/Canvas/views/HomeTabs/MyDashboard.jsx +++ b/client/src/components/Canvas/views/HomeTabs/MyDashboard.jsx @@ -4,7 +4,6 @@ import CustomResizeHandle from '../../CanvasComponents/CustomResizeHandle'; import FirstWidgetButton from '../../CanvasComponents/FirstWidgetButton'; export default function MyDashboard({layout, onLayoutChange, isEditable, isDelete, DeleteWidget, widgetArray, appendWidget}) { - console.log("rendering MyDashboard"); const recipe = useSlotRecipe({ key: "widget" }); const styles = recipe(); // using root recipe for widget below const ResponsiveGridLayout = WidthProvider(GridLayout); // canvas width now adjusts to window size @@ -12,9 +11,6 @@ export default function MyDashboard({layout, onLayoutChange, isEditable, isDelet const handleDragStop = () => { document.body.style.userSelect = ""; }; // allow text highlighting all other times let merged = []; - console.log("widgetArray: ", widgetArray); - console.log("layout: ", layout); - if (widgetArray.length && layout.length) { const widgetMap = new Map(widgetArray.map(item => [item.i, item])); merged = layout.map(item => { @@ -23,7 +19,7 @@ export default function MyDashboard({layout, onLayoutChange, isEditable, isDelet ...widgetMap.get(item.i) }; }); - }; + } // Show large 'Add Widget' button when dashboard is empty if ( !layout.length ) { @@ -36,39 +32,43 @@ export default function MyDashboard({layout, onLayoutChange, isEditable, isDelet bg="gray.150" borderRadius="md" > - + ); } // Show responsive grid of widgets return ( - - } - > - { merged.map((item) => { - const Widget = item.widget; - return ( - - - - ); - }) - } - - + } + > + { merged.map((item) => { + const Widget = item.widget; + return ( + + + + ); + }) + } + ); } diff --git a/client/src/components/Header/Header.jsx b/client/src/components/Header/Header.jsx index a89eed9..60fa076 100644 --- a/client/src/components/Header/Header.jsx +++ b/client/src/components/Header/Header.jsx @@ -1,5 +1,7 @@ -import { chakra, useRecipe, Box, Button, Stack, Text, Flex } from "@chakra-ui/react" +import { useRecipe, Button, Stack, Text, Flex } from "@chakra-ui/react" import UserAvatarMenu from "./UserAvatarMenu.jsx"; +import { useNavigate } from "react-router-dom"; +import { NavLink } from "react-router-dom"; //TODO: Dynamically populate per each user const user = { @@ -8,13 +10,16 @@ const user = { // avatar: "src\\assets\\user_profile.svg" } -export default function Header({ onChangeView }) { +export default function Header() { + const navigate = useNavigate(); const recipe = useRecipe({ key: "header" }); const styles = recipe(); return ( - - + + {user.name} @@ -23,10 +28,9 @@ export default function Header({ onChangeView }) { - + ); } diff --git a/client/src/components/Header/UserAvatarMenu.jsx b/client/src/components/Header/UserAvatarMenu.jsx index 14bbdc9..7741183 100644 --- a/client/src/components/Header/UserAvatarMenu.jsx +++ b/client/src/components/Header/UserAvatarMenu.jsx @@ -1,7 +1,8 @@ -import { Avatar, Menu, Portal, Box } from "@chakra-ui/react" +import { Avatar, Menu, Portal, Box } from "@chakra-ui/react"; +import { NavLink } from "react-router-dom"; -export default function UserAvatarMenu({ onChangeView, name, avatar }) { +export default function UserAvatarMenu({ name, avatar }) { return ( @@ -21,7 +22,7 @@ export default function UserAvatarMenu({ onChangeView, name, avatar }) { {/* zIndex: overlay = 1300 */} - onChangeView("personal")}> + Settings console.log("Log out triggered")}> diff --git a/client/src/components/Sidebar/Sidebar.jsx b/client/src/components/Sidebar/Sidebar.jsx index 4829f91..7fe5267 100644 --- a/client/src/components/Sidebar/Sidebar.jsx +++ b/client/src/components/Sidebar/Sidebar.jsx @@ -1,89 +1,61 @@ import { useSlotRecipe, Box, Button, IconButton } from "@chakra-ui/react"; import { ColorModeButton, useColorMode } from "@/components/ui/color-mode"; +import { useState } from "react"; +import { NavLink } from "react-router-dom"; import Tooltip from "../Canvas/CanvasComponents/Tooltip.jsx"; -import { FaVolcano } from "react-icons/fa6"; -import { FaHome } from "react-icons/fa"; -import { FaGlobeAmericas } from "react-icons/fa"; -import { FaMapMarkerAlt } from "react-icons/fa"; -import { HiUsers } from "react-icons/hi2"; -import { VscThreeBars } from "react-icons/vsc"; -import { MdOutlineSecurity } from "react-icons/md"; -import { IoPersonCircleSharp } from "react-icons/io5"; -import { useState, useEffect, useMemo } from "react"; -import { DASHBOARD_VIEWS } from "@/constants/viewKeys"; -import { KeyRound } from 'lucide-react'; +import { Mountain, House, Earth, MapPin, ShieldUser, Menu, CircleUserRound, KeyRound } from 'lucide-react'; -export default function Sidebar({ view, onChangeView, darkMode, setDarkMode }) { +export default function Sidebar() { + const { toggleColorMode } = useColorMode(); const [isOpen, setIsOpen] = useState(true); const [activeButton, setActiveButton] = useState(0) const recipe = useSlotRecipe({ key: "sidebar" }); const styles = recipe(); - const { toggleColorMode } = useColorMode(); - const buttons = useMemo(() => { - if (["settings", "personal", "security"].includes(view)) { - return [ - {icon: IoPersonCircleSharp, name: "Personal Info", view: "personal"}, - {icon: KeyRound, name: "Security", view: "security"}, - ]; - } - return [ - {icon: FaHome, name: "Home", view: "mydashboard"}, - {icon: FaGlobeAmericas, name: "Global Map", view: "global"}, - {icon: FaMapMarkerAlt, name: "Regional Map", view: "regional"}, - {icon: FaVolcano, name: "Volcano", view: "volcanohome"}, - {icon: HiUsers, name: "Admin", view: "medataentry"} - ]; - }, [view]); + // const buttons = useMemo(() => { + // if (["settings", "personal", "security"].includes(view)) { + // return [ + // {icon: CircleUserRound, name: "Personal Info", url: "/personal"}, + // {icon: KeyRound, name: "Security", url: "/security"}, + // ]; + // } + // return [ + // {icon: House, name: "Home", url: "/mydashboard"}, + // {icon: Earth, name: "Global Map", url: "/global"}, + // {icon: MapPin, name: "Regional Map", url: "/regional"}, + // {icon: Mountain, name: "Volcano", url: "/volcanohome"}, + // {icon: ShieldUser, name: "Admin", url: "/medataentry"} + // ]; + // }, [view]); + + const buttons = [ + {icon: House, name: "Home", url: "/home"}, + {icon: Earth, name: "Global Map", url: "/GlobalMap"}, + {icon: MapPin, name: "Regional Map", url: "/regional-map"}, + {icon: Mountain, name: "Volcano", url: "/volcano"}, + {icon: ShieldUser, name: "Admin", url: "/medataentry"} + ]; const toggleSidebar = () => { if (isOpen) setIsOpen(false); else setIsOpen(true); }; - // Track currrent view from both Sidebar and Canvas when 'view' changes - useEffect(() => { - console.log("Current view = ", view); - const newIndex = buttons.findIndex((btn) => { - if (btn.view === "mydashboard") { - return DASHBOARD_VIEWS.includes(view); - } - return btn.view === view; - }); - if (newIndex !== -1 ) { - setActiveButton(newIndex); - } - }, [view]); - return ( - - - + + + {buttons.map((button, idx) => { const Icon = button.icon; return ( - -