diff --git a/client/.env b/client/.env new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/client/.env @@ -0,0 +1 @@ + diff --git a/client/README.md b/client/README.md index f768e33..175015d 100644 --- a/client/README.md +++ b/client/README.md @@ -1,8 +1,9 @@ -# React + Vite +(1)uninstall the old version Toolpad/core 0.8.1 and install the latest toolpad/core 0.13.0.. + +(2)additional added the latest stripe libraries- + + "@stripe/react-stripe-js": "^3.6.0", + "@stripe/stripe-js": "^7.0.0", -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. -Currently, two official plugins are available: -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh diff --git a/client/package-lock.json b/client/package-lock.json index faf4e00..7b28df8 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,9 +11,30 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.4.4", - "@mui/material": "^6.4.4", + "@mui/lab": "^6.0.0-beta.28", + "@mui/material": "^6.4.8", + "@mui/x-date-pickers": "^7.27.0", + "@reduxjs/toolkit": "^2.6.1", + "@stripe/react-stripe-js": "^3.6.0", + "@stripe/stripe-js": "^7.0.0", + "@tiptap/pm": "^2.11.5", + "@tiptap/react": "^2.11.5", + "@tiptap/starter-kit": "^2.11.5", + "@toolpad/core": "^0.13.0", + "axios": "^1.8.3", + "chart.js": "^4.4.8", + "date-fns": "^4.1.0", + "dayjs": "^1.11.13", + "qrcode": "^1.5.4", + "qrcode.react": "^4.2.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-chartjs-2": "^5.3.0", + "react-dom": "^19.0.0", + "react-redux": "^9.2.0", + "react-router-dom": "^7.2.0", + "redux-persist": "^6.0.0", + "sonner": "^2.0.1", + "speakeasy": "^2.0.0" }, "devDependencies": { "@eslint/js": "^9.19.0", @@ -27,7 +48,7 @@ "eslint-plugin-react-refresh": "^0.4.18", "globals": "^15.14.0", "postcss": "^8.5.2", - "tailwindcss": "^3.3.3", + "tailwindcss": "^3.4.17", "vite": "^6.1.0" } }, @@ -48,7 +69,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -76,7 +96,6 @@ "version": "7.26.8", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -86,7 +105,6 @@ "version": "7.26.9", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -133,7 +151,6 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.26.5", @@ -163,7 +180,6 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", @@ -181,7 +197,6 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -209,33 +224,31 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", - "dev": true, + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -248,7 +261,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -264,7 +276,6 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -277,9 +288,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", - "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -289,14 +300,14 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" @@ -330,9 +341,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -495,13 +506,12 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -512,13 +522,12 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -529,13 +538,12 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -546,13 +554,12 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -563,13 +570,12 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -580,13 +586,12 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -597,13 +602,12 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -614,13 +618,12 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -631,13 +634,12 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -648,13 +650,12 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -665,13 +666,12 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -682,13 +682,12 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -699,13 +698,12 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -716,13 +714,12 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -733,13 +730,12 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -750,13 +746,12 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -767,13 +762,12 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -784,13 +778,12 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -801,13 +794,12 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -818,13 +810,12 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -835,13 +826,12 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -852,13 +842,12 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -869,13 +858,12 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -886,13 +874,12 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -903,13 +890,12 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1073,6 +1059,127 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@fast-csv/format": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", + "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + } + }, + "node_modules/@fast-csv/format/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@fast-csv/parse": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", + "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/@fast-csv/parse/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1205,10 +1312,49 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.69", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.69.tgz", + "integrity": "sha512-r2YyGUXpZxj8rLAlbjp1x2BnMERTZ/dMqd9cClKj2OJ7ALAuiv/9X5E9eHfRc9o/dGRuLSMq/WTjREktJVjxVA==", + "deprecated": "This package has been replaced by @base-ui-components/react", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@floating-ui/react-dom": "^2.1.1", + "@mui/types": "^7.2.21", + "@mui/utils": "^6.4.1", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/core-downloads-tracker": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.4.tgz", - "integrity": "sha512-r+J0EditrekkTtO2CnCBCOGpNaDYwJqz8lH4rj6o/anDcskZFJodBlG8aCJkS8DL/CF/9EHS+Gz53EbmYEnQbw==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.8.tgz", + "integrity": "sha512-vjP4+A1ybyCRhDZC7r5EPWu/gLseFZxaGyPdDl94vzVvk6Yj6gahdaqcjbhkaCrJjdZj90m3VioltWPAnWF/zw==", "license": "MIT", "funding": { "type": "opencollective", @@ -1241,17 +1387,62 @@ } } }, - "node_modules/@mui/material": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.4.tgz", - "integrity": "sha512-ISVPrIsPQsxnwvS40C4u03AuNSPigFeS2+n1qpuEZ94hDsdMi19dQM2JcC9CHEhXecSIQjP1RTyY0mPiSpSrFQ==", + "node_modules/@mui/lab": { + "version": "6.0.0-beta.28", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.0-beta.28.tgz", + "integrity": "sha512-7d/nG5L3IXcdlgGvOcVwOZIQCHxjQOVVEGOtk0t0XSCQnS5zgQ5/KeKE/brWYdxA6ybSm3vp1sfBGq4AeqMCKA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/core-downloads-tracker": "^6.4.4", + "@mui/base": "5.0.0-beta.69", "@mui/system": "^6.4.3", "@mui/types": "^7.2.21", "@mui/utils": "^6.4.3", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^6.4.5", + "@mui/material-pigment-css": "^6.4.3", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.8.tgz", + "integrity": "sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/core-downloads-tracker": "^6.4.8", + "@mui/system": "^6.4.8", + "@mui/types": "~7.2.24", + "@mui/utils": "^6.4.8", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", @@ -1270,7 +1461,7 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^6.4.3", + "@mui/material-pigment-css": "^6.4.8", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -1297,13 +1488,13 @@ "license": "MIT" }, "node_modules/@mui/private-theming": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.3.tgz", - "integrity": "sha512-7x9HaNwDCeoERc4BoEWLieuzKzXu5ZrhRnEM6AUcRXUScQLvF1NFkTlP59+IJfTbEMgcGg1wWHApyoqcksrBpQ==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.8.tgz", + "integrity": "sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/utils": "^6.4.3", + "@mui/utils": "^6.4.8", "prop-types": "^15.8.1" }, "engines": { @@ -1324,9 +1515,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.3.tgz", - "integrity": "sha512-OC402VfK+ra2+f12Gef8maY7Y9n7B6CZcoQ9u7mIkh/7PKwW/xH81xwX+yW+Ak1zBT3HYcVjh2X82k5cKMFGoQ==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.8.tgz", + "integrity": "sha512-oyjx1b1FvUCI85ZMO4trrjNxGm90eLN3Ohy0AP/SqK5gWvRQg1677UjNf7t6iETOKAleHctJjuq0B3aXO2gtmw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", @@ -1358,16 +1549,16 @@ } }, "node_modules/@mui/system": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.3.tgz", - "integrity": "sha512-Q0iDwnH3+xoxQ0pqVbt8hFdzhq1g2XzzR4Y5pVcICTNtoCLJmpJS3vI4y/OIM1FHFmpfmiEC2IRIq7YcZ8nsmg==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.8.tgz", + "integrity": "sha512-gV7iBHoqlsIenU2BP0wq14BefRoZcASZ/4LeyuQglayBl+DfLX5rEd3EYR3J409V2EZpR0NOM1LATAGlNk2cyA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/private-theming": "^6.4.3", - "@mui/styled-engine": "^6.4.3", - "@mui/types": "^7.2.21", - "@mui/utils": "^6.4.3", + "@mui/private-theming": "^6.4.8", + "@mui/styled-engine": "^6.4.8", + "@mui/types": "~7.2.24", + "@mui/utils": "^6.4.8", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -1398,9 +1589,9 @@ } }, "node_modules/@mui/types": { - "version": "7.2.21", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz", - "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==", + "version": "7.2.24", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz", + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==", "license": "MIT", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -1412,13 +1603,13 @@ } }, "node_modules/@mui/utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.3.tgz", - "integrity": "sha512-jxHRHh3BqVXE9ABxDm+Tc3wlBooYz/4XPa0+4AI+iF38rV1/+btJmSUgG4shDtSWVs/I97aDn5jBCt6SF2Uq2A==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.8.tgz", + "integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.21", + "@mui/types": "~7.2.24", "@types/prop-types": "^15.7.14", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -1447,51 +1638,440 @@ "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", "license": "MIT" }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, + "node_modules/@mui/x-date-pickers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.27.0.tgz", + "integrity": "sha512-wSx8JGk4WQ2hTObfQITc+zlmUKNleQYoH1hGocaQlpWpo1HhauDtcQfX6sDN0J0dPT2eeyxDWGj4uJmiSfQKcw==", "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0", + "@mui/x-internals": "7.26.0", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2 || ^3.0.0", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, + "node_modules/@mui/x-internals": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.26.0.tgz", + "integrity": "sha512-VxTCYQcZ02d3190pdvys2TDg9pgbvewAVakEopiOgReKAUhLdRlgGJHcOA/eAuGLyK1YIo26A6Ow6ZKlSRLwMg==", "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "node_modules/@mui/x-data-grid": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.28.3.tgz", + "integrity": "sha512-T2Vd+3pAnI7UD3B1y+Z7e1eB9N7PCgPbn44KhxM3iT1ldT49HHQ7c2wDHm2Qf4F5UHL6dxvsBF3sGnGyfo+JOA==", "license": "MIT", + "peer": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/x-internals": "7.28.0", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/@mui/x-data-grid-premium": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid-premium/-/x-data-grid-premium-7.28.3.tgz", + "integrity": "sha512-nJow8y+EtfzILb1bZaFrGf1w6FY1zPJ0emEBl/8qGohaE/zw8hOvOpM5d2zxSUZ/it04nn1QfNb3GArsN/5VCg==", + "license": "SEE LICENSE IN LICENSE", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/x-data-grid": "7.28.3", + "@mui/x-data-grid-pro": "7.28.3", + "@mui/x-internals": "7.28.0", + "@mui/x-license": "7.28.0", + "@types/format-util": "^1.0.4", + "clsx": "^2.1.1", + "exceljs": "^4.4.0", + "prop-types": "^15.8.1", + "reselect": "^5.1.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-data-grid-premium/node_modules/@mui/x-internals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.28.0.tgz", + "integrity": "sha512-p4GEp/09bLDumktdIMiw+OF4p+pJOOjTG0VUvzNxjbHB9GxbBKoMcHrmyrURqoBnQpWIeFnN/QAoLMFSpfwQbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-data-grid-pro": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid-pro/-/x-data-grid-pro-7.28.3.tgz", + "integrity": "sha512-LPycq0I/plpOBaKPQmOx0iE5azWsMUvFcxO/6CRKJj59KtIVTldfMm7Op4uFmTDjMG/koCxc9TUO+JwoltwR5w==", + "license": "SEE LICENSE IN LICENSE", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/x-data-grid": "7.28.3", + "@mui/x-internals": "7.28.0", + "@mui/x-license": "7.28.0", + "@types/format-util": "^1.0.4", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "reselect": "^5.1.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-data-grid-pro/node_modules/@mui/x-internals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.28.0.tgz", + "integrity": "sha512-p4GEp/09bLDumktdIMiw+OF4p+pJOOjTG0VUvzNxjbHB9GxbBKoMcHrmyrURqoBnQpWIeFnN/QAoLMFSpfwQbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-data-grid/node_modules/@mui/x-internals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.28.0.tgz", + "integrity": "sha512-p4GEp/09bLDumktdIMiw+OF4p+pJOOjTG0VUvzNxjbHB9GxbBKoMcHrmyrURqoBnQpWIeFnN/QAoLMFSpfwQbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-date-pickers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.27.0.tgz", + "integrity": "sha512-wSx8JGk4WQ2hTObfQITc+zlmUKNleQYoH1hGocaQlpWpo1HhauDtcQfX6sDN0J0dPT2eeyxDWGj4uJmiSfQKcw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0", + "@mui/x-internals": "7.26.0", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0", + "@mui/system": "^5.15.14 || ^6.0.0", + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2 || ^3.0.0", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@mui/x-internals": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.26.0.tgz", + "integrity": "sha512-VxTCYQcZ02d3190pdvys2TDg9pgbvewAVakEopiOgReKAUhLdRlgGJHcOA/eAuGLyK1YIo26A6Ow6ZKlSRLwMg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-license": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@mui/x-license/-/x-license-7.28.0.tgz", + "integrity": "sha512-z50lVN4KxW+KB3usEnorEarbWtBxpYQrWfkmJqwJZEaeDO870LghBuhXNt4KEE2jqUU64MQCgZRPszIyrAvXfQ==", + "license": "SEE LICENSE IN LICENSE", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/x-internals": "7.28.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-license/node_modules/@mui/x-internals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.28.0.tgz", + "integrity": "sha512-p4GEp/09bLDumktdIMiw+OF4p+pJOOjTG0VUvzNxjbHB9GxbBKoMcHrmyrURqoBnQpWIeFnN/QAoLMFSpfwQbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0 || ^7.0.0-beta" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, "engines": { "node": ">=14" } @@ -1506,6 +2086,36 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz", + "integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==", + "license": "MIT", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.34.7", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.7.tgz", @@ -1513,7 +2123,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1527,7 +2136,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1541,7 +2149,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1555,7 +2162,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1569,7 +2175,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1583,7 +2188,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1597,7 +2201,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1611,7 +2214,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1625,7 +2227,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1639,7 +2240,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1653,7 +2253,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1667,7 +2266,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1681,7 +2279,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1695,7 +2292,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1709,7 +2305,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1723,7 +2318,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1737,46 +2331,1681 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.34.7", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.7.tgz", + "integrity": "sha512-aeawEKYswsFu1LhDM9RIgToobquzdtSc4jSVqHV8uApz4FVvhFl/mKh92wc8WpFc6aYCothV/03UjY6y7yLgbg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.7", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.7.tgz", + "integrity": "sha512-4ZedScpxxIrVO7otcZ8kCX1mZArtH2Wfj3uFCxRJ9NO80gg1XV0U/b2f/MKaGwj2X3QopHfoWiDQ917FRpwY3w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tiptap/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.11.5.tgz", + "integrity": "sha512-jb0KTdUJaJY53JaN7ooY3XAxHQNoMYti/H6ANo707PsLXVeEqJ9o8+eBup1JU5CuwzrgnDc2dECt2WIGX9f8Jw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.11.5.tgz", + "integrity": "sha512-MZfcRIzKRD8/J1hkt/eYv49060GTL6qGR3NY/oTDuw2wYzbQXXLEbjk8hxAtjwNn7G+pWQv3L+PKFzZDxibLuA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.11.5.tgz", + "integrity": "sha512-OAq03MHEbl7MtYCUzGuwb0VpOPnM0k5ekMbEaRILFU5ZC7cEAQ36XmPIw1dQayrcuE8GZL35BKub2qtRxyC9iA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.11.5.tgz", + "integrity": "sha512-rx+rMd7EEdht5EHLWldpkzJ56SWYA9799b33ustePqhXd6linnokJCzBqY13AfZ9+xp3RsR6C0ZHI9GGea0tIA==", + "license": "MIT", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.11.5.tgz", + "integrity": "sha512-VXwHlX6A/T6FAspnyjbKDO0TQ+oetXuat6RY1/JxbXphH42nLuBaGWJ6pgy6xMl6XY8/9oPkTNrfJw/8/eeRwA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.11.5.tgz", + "integrity": "sha512-xOvHevNIQIcCCVn9tpvXa1wBp0wHN/2umbAZGTVzS+AQtM7BTo0tz8IyzwxkcZJaImONcUVYLOLzt2AgW1LltA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.11.5.tgz", + "integrity": "sha512-ksxMMvqLDlC+ftcQLynqZMdlJT1iHYZorXsXw/n+wuRd7YElkRkd6YWUX/Pq/njFY6lDjKiqFLEXBJB8nrzzBA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.11.5.tgz", + "integrity": "sha512-7I4BRTpIux2a0O2qS3BDmyZ5LGp3pszKbix32CmeVh7lN9dV7W5reDqtJJ9FCZEEF+pZ6e1/DQA362dflwZw2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.11.5.tgz", + "integrity": "sha512-uIN7L3FU0904ec7FFFbndO7RQE/yiON4VzAMhNn587LFMyWO8US139HXIL4O8dpZeYwYL3d1FnDTflZl6CwLlg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.11.5.tgz", + "integrity": "sha512-HsMI0hV5Lwzm530Z5tBeyNCBNG38eJ3qjfdV2OHlfSf3+KOEfn6a5AUdoNaZO02LF79/8+7BaYU2drafag9cxQ==", + "license": "MIT", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.11.5.tgz", + "integrity": "sha512-kcWa+Xq9cb6lBdiICvLReuDtz/rLjFKHWpW3jTTF3FiP3wx4H8Rs6bzVtty7uOVTfwupxZRiKICAMEU6iT0xrQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.11.5.tgz", + "integrity": "sha512-q9doeN+Yg9F5QNTG8pZGYfNye3tmntOwch683v0CCVCI4ldKaLZ0jG3NbBTq+mosHYdgOH2rNbIORlRRsQ+iYQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.11.5.tgz", + "integrity": "sha512-x/MV53psJ9baRcZ4k4WjnCUBMt8zCX7mPlKVT+9C/o+DEs/j/qxPLs95nHeQv70chZpSwCQCt93xMmuF0kPoAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-history": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.11.5.tgz", + "integrity": "sha512-b+wOS33Dz1azw6F1i9LFTEIJ/gUui0Jwz5ZvmVDpL2ZHBhq1Ui0/spTT+tuZOXq7Y/uCbKL8Liu4WoedIvhboQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.11.5.tgz", + "integrity": "sha512-3up2r1Du8/5/4ZYzTC0DjTwhgPI3dn8jhOCLu73m5F3OGvK/9whcXoeWoX103hYMnGDxBlfOje71yQuN35FL4A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.11.5.tgz", + "integrity": "sha512-9VGfb2/LfPhQ6TjzDwuYLRvw0A6VGbaIp3F+5Mql8XVdTBHb2+rhELbyhNGiGVR78CaB/EiKb6dO9xu/tBWSYA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.11.5.tgz", + "integrity": "sha512-Mp5RD/pbkfW1vdc6xMVxXYcta73FOwLmblQlFNn/l/E5/X1DUSA4iGhgDDH4EWO3swbs03x2f7Zka/Xoj3+WLg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.11.5.tgz", + "integrity": "sha512-Cu8KwruBNWAaEfshRQR0yOSaUKAeEwxW7UgbvF9cN/zZuKgK5uZosPCPTehIFCcRe+TBpRtZQh+06f/gNYpYYg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.11.5.tgz", + "integrity": "sha512-YFBWeg7xu/sBnsDIF/+nh9Arf7R0h07VZMd0id5Ydd2Qe3c1uIZwXxeINVtH0SZozuPIQFAT8ICe9M0RxmE+TA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.11.5.tgz", + "integrity": "sha512-PVfUiCqrjvsLpbIoVlegSY8RlkR64F1Rr2RYmiybQfGbg+AkSZXDeO0eIrc03//4gua7D9DfIozHmAKv1KN3ow==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.11.5.tgz", + "integrity": "sha512-Gq1WwyhFpCbEDrLPIHt5A8aLSlf8bfz4jm417c8F/JyU0J5dtYdmx0RAxjnLw1i7ZHE7LRyqqAoS0sl7JHDNSQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-text-style": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.11.5.tgz", + "integrity": "sha512-YUmYl0gILSd/u/ZkOmNxjNXVw+mu8fpC2f8G4I4tLODm0zCx09j9DDEJXSrM5XX72nxJQqtSQsCpNKnL0hfeEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/pm": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.5.tgz", + "integrity": "sha512-z9JFtqc5ZOsdQLd9vRnXfTCQ8v5ADAfRt9Nm7SqP6FUHII8E1hs38ACzf5xursmth/VonJYb5+73Pqxk1hGIPw==", + "license": "MIT", + "dependencies": { + "prosemirror-changeset": "^2.2.1", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.23.0", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.4.1", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.3", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.37.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.11.5.tgz", + "integrity": "sha512-Dp8eHL1G+R/C4+QzAczyb3t1ovexEIZx9ln7SGEM+cT1KHKAw9XGPRgsp92+NQaYI+EdEb/YqoBOSzQcd18/OQ==", + "license": "MIT", + "dependencies": { + "@tiptap/extension-bubble-menu": "^2.11.5", + "@tiptap/extension-floating-menu": "^2.11.5", + "@types/use-sync-external-store": "^0.0.6", + "fast-deep-equal": "^3", + "use-sync-external-store": "^1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.11.5.tgz", + "integrity": "sha512-SLI7Aj2ruU1t//6Mk8f+fqW+18uTqpdfLUJYgwu0CkqBckrkRZYZh6GVLk/02k3H2ki7QkFxiFbZrdbZdng0JA==", + "license": "MIT", + "dependencies": { + "@tiptap/core": "^2.11.5", + "@tiptap/extension-blockquote": "^2.11.5", + "@tiptap/extension-bold": "^2.11.5", + "@tiptap/extension-bullet-list": "^2.11.5", + "@tiptap/extension-code": "^2.11.5", + "@tiptap/extension-code-block": "^2.11.5", + "@tiptap/extension-document": "^2.11.5", + "@tiptap/extension-dropcursor": "^2.11.5", + "@tiptap/extension-gapcursor": "^2.11.5", + "@tiptap/extension-hard-break": "^2.11.5", + "@tiptap/extension-heading": "^2.11.5", + "@tiptap/extension-history": "^2.11.5", + "@tiptap/extension-horizontal-rule": "^2.11.5", + "@tiptap/extension-italic": "^2.11.5", + "@tiptap/extension-list-item": "^2.11.5", + "@tiptap/extension-ordered-list": "^2.11.5", + "@tiptap/extension-paragraph": "^2.11.5", + "@tiptap/extension-strike": "^2.11.5", + "@tiptap/extension-text": "^2.11.5", + "@tiptap/extension-text-style": "^2.11.5", + "@tiptap/pm": "^2.11.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@toolpad/core": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@toolpad/core/-/core-0.8.1.tgz", + "integrity": "sha512-qCLaoHulvIyfrYLULIfuuxELhLQ6cdinebp0GB6hCH16v4oFNKTiwHBSYIK5xODG/vur0nISprch9kAAjJhIAQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/lab": "6.0.0-beta.12", + "@mui/utils": "6.1.4", + "@toolpad/utils": "0.8.1", + "@vitejs/plugin-react": "4.3.2", + "client-only": "^0.0.1", + "invariant": "2.2.4", + "path-to-regexp": "6.3.0", + "prop-types": "15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@mui/icons-material": "5 - 6", + "@mui/material": "5 - 6", + "next": "^14", + "react": "^18", + "react-router-dom": "^6" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react-router-dom": { + "optional": true + } + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@toolpad/core/node_modules/@mui/base": { + "version": "5.0.0-beta.59", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.59.tgz", + "integrity": "sha512-LQZ2907rPMut/2Lq6qSnyP+nqOHLO3buMv91m7SdLpqp/lXU5+8vUXcf5oOwTNis6hfSvYGSQJ493Q00OzxDmQ==", + "deprecated": "This package has been replaced by @base-ui-components/react", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@floating-ui/react-dom": "^2.1.1", + "@mui/types": "^7.2.18", + "@mui/utils": "^6.1.4", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@toolpad/core/node_modules/@mui/lab": { + "version": "6.0.0-beta.12", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.0-beta.12.tgz", + "integrity": "sha512-tcnCs2j3MsEjyvTSRWbFrlLqx65R1EQ+wh5RGRGscgwso+DVicF1eLGSgtTpJ5GhUvwXTgTNGxILSmZdobN+IA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/base": "5.0.0-beta.59", + "@mui/system": "^6.1.4", + "@mui/types": "^7.2.18", + "@mui/utils": "^6.1.4", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^6.1.4", + "@mui/material-pigment-css": "^6.1.4", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@toolpad/core/node_modules/@mui/utils": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.4.tgz", + "integrity": "sha512-v0wXkyh3/Hpw48ivlNvgs4ZT6M8BIEAMdLgvct59rQBggYFhoAVKyliKDzdj37CnIlYau3DYIn7x5bHlRYFBow==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "@mui/types": "^7.2.18", + "@types/prop-types": "^15.7.13", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@toolpad/core/node_modules/@types/react": { + "version": "18.3.20", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", + "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@toolpad/core/node_modules/@vitejs/plugin-react": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz", + "integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/@toolpad/core/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/@toolpad/core/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/@toolpad/core/node_modules/react-is": { + "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==", + "license": "MIT" + }, + "node_modules/@toolpad/core/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/@toolpad/core/node_modules/vite": { + "version": "5.4.17", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.17.tgz", + "integrity": "sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==", + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/@toolpad/utils": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@toolpad/utils/-/utils-0.8.1.tgz", + "integrity": "sha512-GdsxQYXCBK/iyr7kgppgsZaa+2cnQfImlGig6vst1UnhE/OW5omLGrB2jGiUIwuFHRqXqF1AVcyNiLsgGRq4dQ==", + "license": "MIT", + "dependencies": { + "invariant": "2.2.4", + "prettier": "3.3.3", + "react-is": "18.3.1", + "title": "3.5.3", + "yaml": "2.5.1", + "yaml-diff-patch": "2.0.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@toolpad/utils/node_modules/react-is": { + "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==", + "license": "MIT" + }, + "node_modules/@toolpad/utils/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@stripe/react-stripe-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.6.0.tgz", + "integrity": "sha512-zEnaUmTOsu7zhl3RWbZ0l1dRiad+QIbcAYzQfF+yYelURJowhAwesRHKWH+qGAIBEpkO6/VCLFHhVLH9DtPlnw==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@stripe/stripe-js": ">=1.44.1 <8.0.0", + "react": ">=16.8.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" + } + }, + "node_modules/@stripe/stripe-js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.0.0.tgz", + "integrity": "sha512-0AWkP+hoIXB5O34FGY7jh687ZPlOqLqMkJDkiSXcp4TaWWidnxjsZSp0xkjyAWbIz4+j1BFXDAK01Rqb7ceBRA==", + "license": "MIT", + "engines": { + "node": ">=12.16" + } + }, + "node_modules/@tiptap/core": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.11.5.tgz", + "integrity": "sha512-jb0KTdUJaJY53JaN7ooY3XAxHQNoMYti/H6ANo707PsLXVeEqJ9o8+eBup1JU5CuwzrgnDc2dECt2WIGX9f8Jw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.11.5.tgz", + "integrity": "sha512-MZfcRIzKRD8/J1hkt/eYv49060GTL6qGR3NY/oTDuw2wYzbQXXLEbjk8hxAtjwNn7G+pWQv3L+PKFzZDxibLuA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.11.5.tgz", + "integrity": "sha512-OAq03MHEbl7MtYCUzGuwb0VpOPnM0k5ekMbEaRILFU5ZC7cEAQ36XmPIw1dQayrcuE8GZL35BKub2qtRxyC9iA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.11.5.tgz", + "integrity": "sha512-rx+rMd7EEdht5EHLWldpkzJ56SWYA9799b33ustePqhXd6linnokJCzBqY13AfZ9+xp3RsR6C0ZHI9GGea0tIA==", + "license": "MIT", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.11.5.tgz", + "integrity": "sha512-VXwHlX6A/T6FAspnyjbKDO0TQ+oetXuat6RY1/JxbXphH42nLuBaGWJ6pgy6xMl6XY8/9oPkTNrfJw/8/eeRwA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.11.5.tgz", + "integrity": "sha512-xOvHevNIQIcCCVn9tpvXa1wBp0wHN/2umbAZGTVzS+AQtM7BTo0tz8IyzwxkcZJaImONcUVYLOLzt2AgW1LltA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.11.5.tgz", + "integrity": "sha512-ksxMMvqLDlC+ftcQLynqZMdlJT1iHYZorXsXw/n+wuRd7YElkRkd6YWUX/Pq/njFY6lDjKiqFLEXBJB8nrzzBA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.11.5.tgz", + "integrity": "sha512-7I4BRTpIux2a0O2qS3BDmyZ5LGp3pszKbix32CmeVh7lN9dV7W5reDqtJJ9FCZEEF+pZ6e1/DQA362dflwZw2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.11.5.tgz", + "integrity": "sha512-uIN7L3FU0904ec7FFFbndO7RQE/yiON4VzAMhNn587LFMyWO8US139HXIL4O8dpZeYwYL3d1FnDTflZl6CwLlg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.11.5.tgz", + "integrity": "sha512-HsMI0hV5Lwzm530Z5tBeyNCBNG38eJ3qjfdV2OHlfSf3+KOEfn6a5AUdoNaZO02LF79/8+7BaYU2drafag9cxQ==", + "license": "MIT", + "dependencies": { + "tippy.js": "^6.3.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.11.5.tgz", + "integrity": "sha512-kcWa+Xq9cb6lBdiICvLReuDtz/rLjFKHWpW3jTTF3FiP3wx4H8Rs6bzVtty7uOVTfwupxZRiKICAMEU6iT0xrQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.11.5.tgz", + "integrity": "sha512-q9doeN+Yg9F5QNTG8pZGYfNye3tmntOwch683v0CCVCI4ldKaLZ0jG3NbBTq+mosHYdgOH2rNbIORlRRsQ+iYQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.11.5.tgz", + "integrity": "sha512-x/MV53psJ9baRcZ4k4WjnCUBMt8zCX7mPlKVT+9C/o+DEs/j/qxPLs95nHeQv70chZpSwCQCt93xMmuF0kPoAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-history": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.11.5.tgz", + "integrity": "sha512-b+wOS33Dz1azw6F1i9LFTEIJ/gUui0Jwz5ZvmVDpL2ZHBhq1Ui0/spTT+tuZOXq7Y/uCbKL8Liu4WoedIvhboQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.11.5.tgz", + "integrity": "sha512-3up2r1Du8/5/4ZYzTC0DjTwhgPI3dn8jhOCLu73m5F3OGvK/9whcXoeWoX103hYMnGDxBlfOje71yQuN35FL4A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.11.5.tgz", + "integrity": "sha512-9VGfb2/LfPhQ6TjzDwuYLRvw0A6VGbaIp3F+5Mql8XVdTBHb2+rhELbyhNGiGVR78CaB/EiKb6dO9xu/tBWSYA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.11.5.tgz", + "integrity": "sha512-Mp5RD/pbkfW1vdc6xMVxXYcta73FOwLmblQlFNn/l/E5/X1DUSA4iGhgDDH4EWO3swbs03x2f7Zka/Xoj3+WLg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.11.5.tgz", + "integrity": "sha512-Cu8KwruBNWAaEfshRQR0yOSaUKAeEwxW7UgbvF9cN/zZuKgK5uZosPCPTehIFCcRe+TBpRtZQh+06f/gNYpYYg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.11.5.tgz", + "integrity": "sha512-YFBWeg7xu/sBnsDIF/+nh9Arf7R0h07VZMd0id5Ydd2Qe3c1uIZwXxeINVtH0SZozuPIQFAT8ICe9M0RxmE+TA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.11.5.tgz", + "integrity": "sha512-PVfUiCqrjvsLpbIoVlegSY8RlkR64F1Rr2RYmiybQfGbg+AkSZXDeO0eIrc03//4gua7D9DfIozHmAKv1KN3ow==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.11.5.tgz", + "integrity": "sha512-Gq1WwyhFpCbEDrLPIHt5A8aLSlf8bfz4jm417c8F/JyU0J5dtYdmx0RAxjnLw1i7ZHE7LRyqqAoS0sl7JHDNSQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-text-style": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.11.5.tgz", + "integrity": "sha512-YUmYl0gILSd/u/ZkOmNxjNXVw+mu8fpC2f8G4I4tLODm0zCx09j9DDEJXSrM5XX72nxJQqtSQsCpNKnL0hfeEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/pm": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.5.tgz", + "integrity": "sha512-z9JFtqc5ZOsdQLd9vRnXfTCQ8v5ADAfRt9Nm7SqP6FUHII8E1hs38ACzf5xursmth/VonJYb5+73Pqxk1hGIPw==", + "license": "MIT", + "dependencies": { + "prosemirror-changeset": "^2.2.1", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.23.0", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.4.1", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.3", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.37.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.11.5.tgz", + "integrity": "sha512-Dp8eHL1G+R/C4+QzAczyb3t1ovexEIZx9ln7SGEM+cT1KHKAw9XGPRgsp92+NQaYI+EdEb/YqoBOSzQcd18/OQ==", + "license": "MIT", + "dependencies": { + "@tiptap/extension-bubble-menu": "^2.11.5", + "@tiptap/extension-floating-menu": "^2.11.5", + "@types/use-sync-external-store": "^0.0.6", + "fast-deep-equal": "^3", + "use-sync-external-store": "^1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0", + "@tiptap/pm": "^2.7.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.11.5.tgz", + "integrity": "sha512-SLI7Aj2ruU1t//6Mk8f+fqW+18uTqpdfLUJYgwu0CkqBckrkRZYZh6GVLk/02k3H2ki7QkFxiFbZrdbZdng0JA==", + "license": "MIT", + "dependencies": { + "@tiptap/core": "^2.11.5", + "@tiptap/extension-blockquote": "^2.11.5", + "@tiptap/extension-bold": "^2.11.5", + "@tiptap/extension-bullet-list": "^2.11.5", + "@tiptap/extension-code": "^2.11.5", + "@tiptap/extension-code-block": "^2.11.5", + "@tiptap/extension-document": "^2.11.5", + "@tiptap/extension-dropcursor": "^2.11.5", + "@tiptap/extension-gapcursor": "^2.11.5", + "@tiptap/extension-hard-break": "^2.11.5", + "@tiptap/extension-heading": "^2.11.5", + "@tiptap/extension-history": "^2.11.5", + "@tiptap/extension-horizontal-rule": "^2.11.5", + "@tiptap/extension-italic": "^2.11.5", + "@tiptap/extension-list-item": "^2.11.5", + "@tiptap/extension-ordered-list": "^2.11.5", + "@tiptap/extension-paragraph": "^2.11.5", + "@tiptap/extension-strike": "^2.11.5", + "@tiptap/extension-text": "^2.11.5", + "@tiptap/extension-text-style": "^2.11.5", + "@tiptap/pm": "^2.11.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@toolpad/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@toolpad/core/-/core-0.13.0.tgz", + "integrity": "sha512-fnl8sG8XGq+16cQ1uspNkCsVtwtC0979TDCCIJPUXyPGCDU9m8d2QyxmQL6MNqFT1KnfLZkmsFnknht6qlxy0Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.9", + "@mui/utils": "7.0.0-beta.3", + "@standard-schema/spec": "^1.0.0", + "@toolpad/utils": "0.13.0", + "@vitejs/plugin-react": "4.3.4", + "client-only": "^0.0.1", + "dayjs": "1.11.13", + "invariant": "2.2.4", + "path-to-regexp": "6.3.0", + "prop-types": "15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@mui/icons-material": "^6.4.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/material": "^6.4.0 || ^7.0.0 || ^7.0.0-beta", + "@mui/x-data-grid": "^7", + "@mui/x-data-grid-premium": "^7", + "@mui/x-data-grid-pro": "^7", + "@mui/x-date-pickers": "^7", + "next": "^14 || ^15", + "react": "^18 || ^19", + "react-router": "^7" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react-router": { + "optional": true + } + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.7.tgz", - "integrity": "sha512-aeawEKYswsFu1LhDM9RIgToobquzdtSc4jSVqHV8uApz4FVvhFl/mKh92wc8WpFc6aYCothV/03UjY6y7yLgbg==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/@toolpad/core/node_modules/@mui/utils": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.0.0-beta.3.tgz", + "integrity": "sha512-wpyhHEadzRe8gqHACvEqLTiyEMNOBbrNdtPC8kIVPIfFYlwi7F62iC4p2TUpjF/Pu79etWG1K77diKysR/oWYQ==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/runtime": "^7.26.9", + "@mui/types": "^7.2.23", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.7.tgz", - "integrity": "sha512-4ZedScpxxIrVO7otcZ8kCX1mZArtH2Wfj3uFCxRJ9NO80gg1XV0U/b2f/MKaGwj2X3QopHfoWiDQ917FRpwY3w==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@toolpad/core/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/@toolpad/utils": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@toolpad/utils/-/utils-0.13.0.tgz", + "integrity": "sha512-8zvJWFOkcv6bMXPOczB47DigNu+CqOgLAu7pUv69+1mGVXMO/Gzk2TQhSHTL71eVRChrE1MKQ/PPZsowPHxFYg==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "invariant": "2.2.4", + "prettier": "3.4.2", + "react-is": "^19.0.0", + "title": "4.0.1", + "yaml": "2.5.1", + "yaml-diff-patch": "2.0.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@toolpad/utils/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/@toolpad/utils/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -1790,7 +4019,6 @@ "version": "7.6.8", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" @@ -1800,7 +4028,6 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", @@ -1811,19 +4038,30 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, "license": "MIT" }, + "node_modules/@types/format-util": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/format-util/-/format-util-1.0.4.tgz", + "integrity": "sha512-xrCYOdHh5zA3LUrn6CvspYwlzSWxPso11Lx32WnAG6KvLCRecKZ/Rh21PLXUkzUFsQmrGcx/traJAFjR6dVS5Q==", + "license": "MIT", + "peer": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1831,6 +4069,39 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", + "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -1871,11 +4142,16 @@ "@types/react": "*" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@vitejs/plugin-react": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.26.0", @@ -1948,7 +4224,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1981,18 +4256,139 @@ "node": ">= 8" } }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { @@ -2131,6 +4527,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT", + "peer": true + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -2141,6 +4544,12 @@ "node": ">= 0.4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -2195,6 +4604,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -2234,9 +4654,59 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, + "node_modules/base32.js": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz", + "integrity": "sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2250,11 +4720,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "license": "MIT", + "peer": true + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -2278,7 +4766,6 @@ "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2307,6 +4794,60 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "peer": true, + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2330,7 +4871,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2366,6 +4906,15 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2380,7 +4929,6 @@ "version": "1.0.30001699", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2397,11 +4945,23 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "license": "MIT/X11", + "peer": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -2414,6 +4974,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2452,6 +5024,95 @@ "node": ">= 6" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clipboardy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", + "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==", + "license": "MIT", + "dependencies": { + "execa": "^8.0.1", + "is-wsl": "^3.1.0", + "is64bit": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2465,7 +5126,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2478,9 +5138,20 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2491,20 +5162,50 @@ "node": ">= 6" } }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT", + "peer": true + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -2530,11 +5231,49 @@ "node": ">= 6" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2618,6 +5357,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -2635,6 +5390,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2678,6 +5442,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2685,6 +5458,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -2719,7 +5498,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -2730,6 +5508,56 @@ "node": ">= 0.4" } }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2741,7 +5569,6 @@ "version": "1.5.101", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz", "integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==", - "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { @@ -2751,6 +5578,40 @@ "dev": true, "license": "MIT" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2830,7 +5691,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2840,7 +5700,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2878,7 +5737,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -2891,7 +5749,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2935,10 +5792,9 @@ } }, "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", - "dev": true, + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -2948,38 +5804,37 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.2", + "@esbuild/android-arm": "0.25.2", + "@esbuild/android-arm64": "0.25.2", + "@esbuild/android-x64": "0.25.2", + "@esbuild/darwin-arm64": "0.25.2", + "@esbuild/darwin-x64": "0.25.2", + "@esbuild/freebsd-arm64": "0.25.2", + "@esbuild/freebsd-x64": "0.25.2", + "@esbuild/linux-arm": "0.25.2", + "@esbuild/linux-arm64": "0.25.2", + "@esbuild/linux-ia32": "0.25.2", + "@esbuild/linux-loong64": "0.25.2", + "@esbuild/linux-mips64el": "0.25.2", + "@esbuild/linux-ppc64": "0.25.2", + "@esbuild/linux-riscv64": "0.25.2", + "@esbuild/linux-s390x": "0.25.2", + "@esbuild/linux-x64": "0.25.2", + "@esbuild/netbsd-arm64": "0.25.2", + "@esbuild/netbsd-x64": "0.25.2", + "@esbuild/openbsd-arm64": "0.25.2", + "@esbuild/openbsd-x64": "0.25.2", + "@esbuild/sunos-x64": "0.25.2", + "@esbuild/win32-arm64": "0.25.2", + "@esbuild/win32-ia32": "0.25.2", + "@esbuild/win32-x64": "0.25.2" } }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3207,11 +6062,68 @@ "node": ">=0.10.0" } }, + "node_modules/exceljs": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz", + "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==", + "license": "MIT", + "peer": true, + "dependencies": { + "archiver": "^5.0.0", + "dayjs": "^1.8.34", + "fast-csv": "^4.3.1", + "jszip": "^3.10.1", + "readable-stream": "^3.6.0", + "saxes": "^5.0.1", + "tmp": "^0.2.0", + "unzipper": "^0.10.11", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-csv": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", + "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@fast-csv/format": "4.3.5", + "@fast-csv/parse": "4.3.6" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3244,6 +6156,12 @@ "node": ">= 6" } }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "license": "MIT" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3338,6 +6256,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -3371,6 +6309,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3385,11 +6338,24 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT", + "peer": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "peer": true + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -3397,7 +6363,24 @@ "darwin" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" } }, "node_modules/function-bind": { @@ -3444,17 +6427,24 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -3479,7 +6469,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -3489,6 +6478,18 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -3601,7 +6602,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3610,6 +6610,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "license": "ISC", + "peer": true + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -3627,7 +6634,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3666,7 +6672,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3679,7 +6684,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -3712,6 +6716,36 @@ "react-is": "^16.7.0" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3722,6 +6756,33 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT", + "peer": true + }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -3748,6 +6809,25 @@ "node": ">=0.8.19" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "peer": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC", + "peer": true + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -3763,6 +6843,15 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -3916,6 +7005,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3946,7 +7050,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3984,6 +7087,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -4072,6 +7193,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -4169,6 +7302,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is64bit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is64bit/-/is64bit-2.0.0.tgz", + "integrity": "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==", + "license": "MIT", + "dependencies": { + "system-architecture": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -4180,7 +7343,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/iterator.prototype": { @@ -4221,7 +7383,7 @@ "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -4289,7 +7451,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -4314,6 +7475,59 @@ "node": ">=4.0" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "peer": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -4324,6 +7538,59 @@ "json-buffer": "3.0.1" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4338,14 +7605,27 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -4354,6 +7634,22 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "license": "ISC", + "peer": true + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4370,6 +7666,84 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==", + "license": "MIT", + "peer": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4377,6 +7751,20 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT", + "peer": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4393,22 +7781,49 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4419,25 +7834,57 @@ "node": ">= 8" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "mime-db": "1.52.0" }, "engines": { - "node": ">=8.6" + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -4446,6 +7893,16 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -4456,6 +7913,19 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4478,7 +7948,6 @@ "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, "funding": [ { "type": "github", @@ -4504,14 +7973,12 @@ "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4527,6 +7994,33 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4643,6 +8137,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oppa": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/oppa/-/oppa-0.4.0.tgz", + "integrity": "sha512-DFvM3+F+rB/igo3FRnkDWitjZgBH9qZAn68IacYHsqbZBKwuTA+LdD4zSJiQtgQpWq7M08we5FlGAVHz0yW7PQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4661,6 +8192,12 @@ "node": ">= 0.8.0" } }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "license": "MIT" + }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -4679,6 +8216,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4711,6 +8257,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -4718,6 +8273,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)", + "peer": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4752,17 +8314,25 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4798,6 +8368,12 @@ "dev": true, "license": "ISC" }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -4846,6 +8422,15 @@ "node": ">= 6" } }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -4857,10 +8442,9 @@ } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", - "dev": true, + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -4961,106 +8545,316 @@ ], "license": "MIT", "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT", + "peer": true + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prosemirror-changeset": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz", + "integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==", + "license": "MIT", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.0.tgz", + "integrity": "sha512-6toodS4R/Aah5pdsrIwnTYPEjW70SlO5a66oo5Kk+CIrgJz3ukOoS+FYDGqvQlAX5PxoGWDX1oD++tn5X3pyRA==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz", + "integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", + "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz", + "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz", + "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", + "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", + "license": "MIT", + "dependencies": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz", + "integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==", + "license": "MIT", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.0.tgz", + "integrity": "sha512-/8XUmxWf0pkj2BmtqZHYJipTBMHIdVjuvFzMvEoxrtyGNmfvdhBiRwYt/eFwy2wA9DtBW3RLqvZnjurEkHaFCw==", + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.25.0" } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" } }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/prosemirror-state": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", + "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", "license": "MIT", "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" } }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, + "node_modules/prosemirror-tables": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.6.4.tgz", + "integrity": "sha512-TkDY3Gw52gRFRfRn2f4wJv5WOgAOXLJA2CQJYIJ5+kdFbfj3acR4JUW6LX2e1hiEBiUwvEhzH5a3cZ5YSztpIA==", "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "prosemirror-keymap": "^1.2.2", + "prosemirror-model": "^1.24.1", + "prosemirror-state": "^1.4.3", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.37.2" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" + "node_modules/prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "license": "MIT", + "dependencies": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, + "node_modules/prosemirror-transform": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.3.tgz", + "integrity": "sha512-Nhh/+1kZGRINbEHmVu39oynhcap4hWTs/BlU7NnxWj3+l0qi8I1mu67v6mMdEe/ltD8hHvU4FV6PHiCw2VSpMw==", "license": "MIT", - "engines": { - "node": ">= 0.8.0" + "dependencies": { + "prosemirror-model": "^1.21.0" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/prosemirror-view": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.38.1.tgz", + "integrity": "sha512-4FH/uM1A4PNyrxXbD+RAbAsf0d/mM0D/wAKSVVWK7o0A9Q/oOXJBrw786mBf2Vnrs/Edly6dH6Z2gsb7zWwaUw==", "license": "MIT", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5071,6 +8865,41 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode.react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", + "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5101,6 +8930,16 @@ "node": ">=0.10.0" } }, + "node_modules/react-chartjs-2": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz", + "integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==", + "license": "MIT", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-dom": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", @@ -5119,16 +8958,78 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.2.0.tgz", + "integrity": "sha512-fXyqzPgCPZbqhrk7k3hPcCpYIlQ2ugIXDboHUzhJISFVy2DEPsmHgN588MyGmkIOv3jDgNfUE3kJi83L28s/LQ==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.2.0.tgz", + "integrity": "sha512-cU7lTxETGtQRQbafJubvZKHEn5izNABxZhBY0Jlzdv0gqQhCPQt2J8aN5ZPjS6mQOXn5NnirWNh+FpE8TTYN0Q==", + "license": "MIT", + "dependencies": { + "react-router": "7.2.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -5155,6 +9056,54 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -5168,6 +9117,30 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-persist": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", + "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", + "license": "MIT", + "peerDependencies": { + "redux": ">4.0.0" + } + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5218,6 +9191,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -5256,11 +9250,46 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.34.7", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.7.tgz", "integrity": "sha512-8qhyN0oZ4x0H6wmBgfKxJtxM7qS98YJ0k0kNh5ECVtuchIJ7z9IVVvzpmtQyT10PXKMtBxYr1wQ5Apg8RS8kXQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.6" @@ -5295,6 +9324,12 @@ "fsevents": "~2.3.2" } }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5339,6 +9374,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -5374,6 +9430,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "license": "ISC", + "peer": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/scheduler": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", @@ -5384,12 +9453,23 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -5439,11 +9519,17 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT", + "peer": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -5456,7 +9542,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5542,7 +9627,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -5551,6 +9635,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sonner": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.1.tgz", + "integrity": "sha512-FRBphaehZ5tLdLcQ8g2WOIRE+Y7BCfWi5Zyd8bCvBjiW8TxxAyoWZIxS661Yz6TGPqFQ4VLzOF89WEYhfynSFQ==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5564,12 +9658,33 @@ "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, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, + "node_modules/speakeasy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz", + "integrity": "sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==", + "license": "MIT", + "dependencies": { + "base32.js": "0.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -5772,6 +9887,18 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5818,7 +9945,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -5839,35 +9965,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/system-architecture": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", + "integrity": "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", @@ -5898,6 +10036,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -5921,6 +10076,51 @@ "node": ">=0.8" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "license": "MIT", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, + "node_modules/title": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/title/-/title-4.0.1.tgz", + "integrity": "sha512-xRnPkJx9nvE5MF6LkB5e8QJjE2FW8269wTu/LQdf7zZqBgPly0QJPf/CWAo7srj5so4yXfoLEdCFgurlpi47zg==", + "license": "MIT", + "dependencies": { + "arg": "^5.0.0", + "chalk": "^5.0.0", + "clipboardy": "^4.0.0" + }, + "bin": { + "title": "dist/esm/bin.js" + } + }, + "node_modules/title/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5934,6 +10134,16 @@ "node": ">=8.0" } }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "license": "MIT/X11", + "peer": true, + "engines": { + "node": "*" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -5941,6 +10151,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6032,6 +10248,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -6051,11 +10273,77 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", + "peer": true + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6092,22 +10380,39 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", - "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", - "dev": true, + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "license": "MIT", "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.5.1", + "esbuild": "^0.25.0", + "postcss": "^8.5.3", "rollup": "^4.30.1" }, "bin": { @@ -6171,11 +10476,16 @@ } } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -6254,6 +10564,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/which-typed-array": { "version": "1.1.18", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", @@ -6380,18 +10696,36 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC", + "peer": true + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT", + "peer": true + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yaml": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -6400,6 +10734,153 @@ "node": ">= 14" } }, + "node_modules/yaml-diff-patch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yaml-diff-patch/-/yaml-diff-patch-2.0.0.tgz", + "integrity": "sha512-RhfIQPGcKSZhsUmsczXAeg5jNhWXk3tAmhl2kjfZthdyaL0XXXOpvRozUp22HvPStmZsHu8T30/UEfX9oIwGxw==", + "license": "MIT", + "dependencies": { + "fast-json-patch": "^3.1.0", + "oppa": "^0.4.0", + "yaml": "^2.0.0-10" + }, + "bin": { + "yaml-diff-patch": "dist/bin/yaml-patch.js", + "yaml-overwrite": "dist/bin/yaml-patch.js", + "yaml-patch": "dist/bin/yaml-patch.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -6412,6 +10893,65 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } } } } diff --git a/client/package.json b/client/package.json index 539eb9e..98dcb40 100644 --- a/client/package.json +++ b/client/package.json @@ -13,9 +13,30 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.4.4", - "@mui/material": "^6.4.4", + "@mui/lab": "^6.0.0-beta.28", + "@mui/material": "^6.4.8", + "@mui/x-date-pickers": "^7.27.0", + "@reduxjs/toolkit": "^2.6.1", + "@stripe/react-stripe-js": "^3.6.0", + "@stripe/stripe-js": "^7.0.0", + "@tiptap/pm": "^2.11.5", + "@tiptap/react": "^2.11.5", + "@tiptap/starter-kit": "^2.11.5", + "@toolpad/core": "^0.13.0", + "axios": "^1.8.3", + "chart.js": "^4.4.8", + "date-fns": "^4.1.0", + "dayjs": "^1.11.13", + "qrcode": "^1.5.4", + "qrcode.react": "^4.2.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-chartjs-2": "^5.3.0", + "react-dom": "^19.0.0", + "react-redux": "^9.2.0", + "react-router-dom": "^7.2.0", + "redux-persist": "^6.0.0", + "sonner": "^2.0.1", + "speakeasy": "^2.0.0" }, "devDependencies": { "@eslint/js": "^9.19.0", @@ -29,7 +50,7 @@ "eslint-plugin-react-refresh": "^0.4.18", "globals": "^15.14.0", "postcss": "^8.5.2", - "tailwindcss": "^3.3.3", + "tailwindcss": "^3.4.17", "vite": "^6.1.0" } } diff --git a/client/public/Home1.jpg b/client/public/Home1.jpg new file mode 100644 index 0000000..58c04e6 Binary files /dev/null and b/client/public/Home1.jpg differ diff --git a/client/public/categorybg.jpg b/client/public/categorybg.jpg new file mode 100644 index 0000000..7838cbc Binary files /dev/null and b/client/public/categorybg.jpg differ diff --git a/client/public/graph1.png b/client/public/graph1.png new file mode 100644 index 0000000..9f224c4 Binary files /dev/null and b/client/public/graph1.png differ diff --git a/client/public/logo.png b/client/public/logo.png new file mode 100644 index 0000000..dbe662e Binary files /dev/null and b/client/public/logo.png differ diff --git a/client/public/pc1.png b/client/public/pc1.png new file mode 100644 index 0000000..2f84b6a Binary files /dev/null and b/client/public/pc1.png differ diff --git a/client/public/proc.png b/client/public/proc.png new file mode 100644 index 0000000..81e43c4 Binary files /dev/null and b/client/public/proc.png differ diff --git a/client/public/processorbannernew.jpg b/client/public/processorbannernew.jpg new file mode 100644 index 0000000..709df7e Binary files /dev/null and b/client/public/processorbannernew.jpg differ diff --git a/client/public/rambanner.jpg b/client/public/rambanner.jpg new file mode 100644 index 0000000..85a773c Binary files /dev/null and b/client/public/rambanner.jpg differ diff --git a/client/public/sub0.png b/client/public/sub0.png new file mode 100644 index 0000000..81e43c4 Binary files /dev/null and b/client/public/sub0.png differ diff --git a/client/public/sub1.png b/client/public/sub1.png new file mode 100644 index 0000000..c0a86b4 Binary files /dev/null and b/client/public/sub1.png differ diff --git a/client/public/vite.svg b/client/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/client/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/Admin/AdminProfile.jsx b/client/src/Admin/AdminProfile.jsx new file mode 100644 index 0000000..043c58e --- /dev/null +++ b/client/src/Admin/AdminProfile.jsx @@ -0,0 +1,621 @@ +import React, { useState, useEffect } from "react"; +import { Box, Paper, Divider, Typography, TextField, Button, Grid } from "@mui/material"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { useSelector, useDispatch } from "react-redux"; +import { setAuthUser } from "../Store/authSlice.js"; +import axios from "axios"; +import { toast } from "sonner"; +import { useNavigate } from "react-router-dom"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' +import { PrimaryButton } from '../AtomicComponents/Buttons/Buttons'; + +export default function AdminProfile() { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const user = useSelector((state) => state.auth.user); + + const [editable, setEditable] = useState(false); + const [uploading, setUploading] = useState(false); + const [formData, setFormData] = useState({ + name: user?.name || "", + email: user?.email || "", + firstName: user?.firstName || "", + lastName: user?.lastName || "", + address: user?.address || "", + profilePicture: user?.profilePicture || "", + }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + if (user) { + setFormData({ + name: user.name, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + address: user.address, + profilePicture: user.profilePicture, + }); + } + }, [user]); + + const handleChange = (e) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value, + }); + }; + + const handleImageUpload = async (e) => { + const file = e.target.files[0]; + if (!file) return; + + const formData = new FormData(); + formData.append("file", file); + formData.append("upload_preset", "profile_pictures"); + + try { + setUploading(true); + const response = await axios.post( + `https://api.cloudinary.com/v1_1/dfdjzbfjn/image/upload`, + formData + ); + + setFormData(prev => ({ + ...prev, + profilePicture: response.data.secure_url + })); + toast.success("Profile picture updated successfully"); + } catch (error) { + toast.error("Image upload failed"); + console.error("Cloudinary upload error:", error); + } finally { + setUploading(false); + } + }; + + const toggleEditable = () => { + if (editable) { + // Reset form data if canceling edits + setFormData({ + name: user.name, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + address: user.address, + profilePicture: user.profilePicture, + }); + } + setEditable(!editable); + }; + + // Updated handleSubmit function +const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setError(null); + + try { + // Validate required fields + if (!formData.email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) { + throw new Error('Invalid email format'); + } + + // Send only allowed fields + const updateData = { + name: formData.name.trim(), + email: formData.email.trim(), + firstName: formData.firstName.trim(), + lastName: formData.lastName.trim(), + address: formData.address.trim(), + profilePicture: formData.profilePicture || user.profilePicture + }; + const response = await axios.post( + `http://localhost:8000/api/v1/users/update-profile`, + updateData, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${localStorage.getItem('accessToken')}` + }, + withCredentials: true + } + ); + + dispatch(setAuthUser(response.data.user)); + toast.success('Profile updated successfully'); + setEditable(false); + + } catch (error) { + const serverError = error.response?.data?.error; + const validationErrors = error.response?.data?.fields?.join(', ') || []; + + setError(validationErrors + ? `Invalid fields: ${validationErrors}` + : serverError || 'An error occurred. Please try again.' + ); + + toast.error(`Update failed: ${error.message}`); + + } finally { + setLoading(false); + } +}; + return ( + + +
+ + +
+ + + {formData.profilePicture ? ( +
+ Profile +
+ + ) : ( + + )} + + {editable && ( + + + + + )} +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + {editable && ( + + + + )} + +
+ + {error && ( + + {error} + + )} +
+
+ ); +} +import React, { useState, useEffect } from "react"; +import { Box, Paper, Divider, Typography, TextField, Button, Grid } from "@mui/material"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { useSelector, useDispatch } from "react-redux"; +import { setAuthUser } from "../Store/authSlice.js"; +import axios from "axios"; +import { toast } from "sonner"; +import { useNavigate } from "react-router-dom"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' +import Iconset from "../AtomicComponents/Icons/Iconset"; +import theme from "../AtomicComponents/theme"; +import { DashboardLayout } from "@toolpad/core"; +import { Outlet } from "react-router-dom"; +import ToolpadFixer from "../MoleculesComponents/ToolpadFixer"; + + +export default function AdminProfile() { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const user = useSelector((state) => state.auth.user); + + const [editable, setEditable] = useState(false); + const [uploading, setUploading] = useState(false); + const [formData, setFormData] = useState({ + name: user?.name || "", + email: user?.email || "", + firstName: user?.firstName || "", + lastName: user?.lastName || "", + address: user?.address || "", + profilePicture: user?.profilePicture || "", + }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + if (user) { + setFormData({ + name: user.name, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + address: user.address, + profilePicture: user.profilePicture, + }); + } + }, [user]); + + const handleChange = (e) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value, + }); + }; + + const handleImageUpload = async (e) => { + const file = e.target.files[0]; + if (!file) return; + + const formData = new FormData(); + formData.append("file", file); + formData.append("upload_preset", "profile_pictures"); + + try { + setUploading(true); + const response = await axios.post( + `https://api.cloudinary.com/v1_1/dfdjzbfjn/image/upload`, + formData + ); + + setFormData(prev => ({ + ...prev, + profilePicture: response.data.secure_url + })); + toast.success("Profile picture updated successfully"); + } catch (error) { + toast.error("Image upload failed"); + console.error("Cloudinary upload error:", error); + } finally { + setUploading(false); + } + }; + + const toggleEditable = () => { + if (editable) { + // Reset form data if canceling edits + setFormData({ + name: user.name, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + address: user.address, + profilePicture: user.profilePicture, + }); + } + setEditable(!editable); + }; + + // Updated handleSubmit function +const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + setError(null); + + try { + // Validate required fields + if (!formData.email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) { + throw new Error('Invalid email format'); + } + + // Send only allowed fields + const updateData = { + name: formData.name.trim(), + email: formData.email.trim(), + firstName: formData.firstName.trim(), + lastName: formData.lastName.trim(), + address: formData.address.trim(), + profilePicture: formData.profilePicture || user.profilePicture + }; + const response = await axios.post( + `http://localhost:8000/api/v1/users/update-profile`, + updateData, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${localStorage.getItem('accessToken')}` + }, + withCredentials: true + } + ); + + dispatch(setAuthUser(response.data.user)); + toast.success('Profile updated successfully'); + setEditable(false); + + } catch (error) { + const serverError = error.response?.data?.error; + const validationErrors = error.response?.data?.fields?.join(', ') || []; + + setError(validationErrors + ? `Invalid fields: ${validationErrors}` + : serverError || 'An error occurred. Please try again.' + ); + + toast.error(`Update failed: ${error.message}`); + + } finally { + setLoading(false); + } +}; + return ( +
+ +
+ + +
+ + +
+ + + {formData.profilePicture ? ( +
+ Profile +
+ + ) : ( + + )} + + {editable && ( + + )} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + {editable && ( + + + + )} + +
+ + {error && ( + + {error} + + )} +
+
+
+
+ ); +} diff --git a/client/src/Admin/AdminSetting.jsx b/client/src/Admin/AdminSetting.jsx new file mode 100644 index 0000000..91a5fd9 --- /dev/null +++ b/client/src/Admin/AdminSetting.jsx @@ -0,0 +1,388 @@ +import React, { useState } from "react"; +import { useSelector ,useDispatch } from "react-redux"; +import { + Box, + Paper, + Divider, + Typography, + TextField, + Button, + Grid, + CircularProgress +} from "@mui/material"; +import axios from "axios"; +import { toast } from "sonner"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' +import { setAuthUser } from "../Store/authSlice.js"; + +export default function AdminSettings() { + const user = useSelector((state) => state.auth.user); + const dispatch = useDispatch(); + + const [passwordForm, setPasswordForm] = useState({ + currentPassword: "", + newPassword: "", + confirmPassword: "" + }); + const [twoFAForm, setTwoFAForm] = useState({ + token: "" + }); + const [qrCode, setQrCode] = useState(""); + const [loading, setLoading] = useState({ + password: false, + twoFAEnable: false, + twoFADisable: false + }); + const [errors, setErrors] = useState({ + password: {}, + twoFA: {} + }); + + // Password Change Handlers + const handlePasswordChange = (e) => { + setPasswordForm({ + ...passwordForm, + [e.target.name]: e.target.value + }); + setErrors({ ...errors, password: {} }); + }; + + const validatePasswordForm = () => { + const newErrors = {}; + + if (!passwordForm.currentPassword) { + newErrors.currentPassword = "Current password is required"; + } + + if (!passwordForm.newPassword) { + newErrors.newPassword = "New password is required"; + } else if (passwordForm.newPassword.length < 8) { + newErrors.newPassword = "Password must be at least 8 characters"; + } + + if (passwordForm.newPassword !== passwordForm.confirmPassword) { + newErrors.confirmPassword = "Passwords do not match"; + } + + setErrors({ ...errors, password: newErrors }); + return Object.keys(newErrors).length === 0; + }; + + const handlePasswordSubmit = async (e) => { + e.preventDefault(); + if (!validatePasswordForm()) return; + + setLoading({ ...loading, password: true }); + try { + await axios.post( + `http://localhost:8000/api/v1/users/change-password`, + { + currentPassword: passwordForm.currentPassword, + newPassword: passwordForm.newPassword, + confirmPassword: passwordForm.confirmPassword + }, + { + headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, + withCredentials: true + } + ); + + // Show success toast + toast.success("Password changed successfully!"); + + // Clear the form fields + setPasswordForm({ + currentPassword: "", + newPassword: "", + confirmPassword: "" + }); + } catch (error) { + const errorMessage = error.response?.data?.message || "Password change failed"; + const validationErrors = error.response?.data?.errors; + if (validationErrors) { + setErrors({ password: validationErrors }); + } else { + toast.error(errorMessage); + } + } + finally { + // Reset the loading state + setLoading({ ...loading, password: false }); + } + }; + + // 2FA Handlers + const generate2FASecret = async () => { + setLoading({ ...loading, twoFAEnable: true }); + try { + const response = await axios.post( + "http://localhost:8000/api/v1/users/2fa/generate", + {}, + { headers: { Authorization: `Bearer ${localStorage.getItem("token")}` } } + ); + + // Verify the response structure + console.log("2FA Generation Response:", response.data); + + const otpUrl = response.data?.otpauth_url || response.data?.qr; +if (!otpUrl) { + toast.error("QR code generation failed. Try again."); + return; +} + + + setQrCode(otpUrl); + toast.success("Scan the QR code with your authenticator app"); + } catch (error) { + console.error("2FA Generation Error:", error); + toast.error(error.response?.data?.message || "Failed to generate QR code"); + } finally { + setLoading({ ...loading, twoFAEnable: false }); + } + }; + + const handle2FAChange = (e) => { + setTwoFAForm({ ...twoFAForm, [e.target.name]: e.target.value }); + setErrors({ ...errors, twoFA: {} }); + }; + + const handle2FAEnable = async (e) => { + e.preventDefault(); + setLoading({ ...loading, twoFAEnable: true }); + + try { + await axios.post( + "http://localhost:8000/api/v1/users/2fa/enable", + { token: twoFAForm.token }, + { + headers: { + Authorization: `Bearer ${localStorage.getItem("token")}` + } + } + ); + + toast.success("2FA enabled successfully"); + dispatch(setAuthUser({ ...user, is2FAEnabled: true })); + + setTwoFAForm({ token: "" }); + setQrCode(""); + + + + } catch (error) { + const errorMessage = error.response?.data?.message || "2FA enable failed"; + toast.error(errorMessage); + } finally { + setLoading({ ...loading, twoFAEnable: false }); + } + }; + + const handle2FADisable = async () => { + setLoading({ ...loading, twoFADisable: true }); + + try { + await axios.post( + "http://localhost:8000/api/v1/users/2fa/disable", + {}, + { + headers: { + Authorization: `Bearer ${localStorage.getItem("token")}` + } + } + ); + dispatch(setAuthUser({ ...user, is2FAEnabled: false })); + + toast.success("2FA disabled successfully"); + setQrCode(""); + } catch (error) { + const errorMessage = error.response?.data?.message || "2FA disable failed"; + toast.error(errorMessage); + } finally { + setLoading({ ...loading, twoFADisable: false }); + } + }; + + return ( + +
+ + +
+ {/* Password Change Section */} + + + Change Password + + +
+ + + + + + + + + + + + + + + + + +
+
+ + {/* 2FA Section */} + + + Two-Factor Authentication + + + {user?.is2FAEnabled ? ( + + + 2FA is currently enabled for your account + + + + ) : ( + + {qrCode ? ( +
+ + +
+ QR Code + {loading.twoFAEnable && ( +
+ +
+ )} +
+ + Scan with authenticator app + +
+ + + + + +
+
+ ) : ( + + )} +
+ )} +
+
+ ); +} diff --git a/client/src/Admin/Complaints.jsx b/client/src/Admin/Complaints.jsx new file mode 100644 index 0000000..7ddc6c7 --- /dev/null +++ b/client/src/Admin/Complaints.jsx @@ -0,0 +1,323 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + TextField, + Button, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Select, + MenuItem, + InputLabel, + FormControl, + IconButton, + Avatar, + Typography, + Box, + TablePagination +} from '@mui/material'; +import ReplyIcon from '@mui/icons-material/Reply'; +import { toast } from 'sonner'; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' + +const Complaints = () => { + const [complaints, setComplaints] = useState([]); + const [searchTerm, setSearchTerm] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [responseText, setResponseText] = useState(''); + const [openDialog, setOpenDialog] = useState(false); + const [selectedComplaint, setSelectedComplaint] = useState(null); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + + const handleChangePage = (event, newPage) => setPage(newPage); + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + const fetchComplaints = async () => { + try { + const response = await axios.get('http://localhost:8000/api/complaints/admin', { + params: { search: searchTerm, status: statusFilter } + }); + setComplaints(response.data); + } catch (err) { + alert('Failed to fetch complaints'); + } + }; + + useEffect(() => { fetchComplaints(); }, []); + + const handleRespond = async () => { + try { + await axios.put(`http://localhost:8000/api/complaints/admin/respond/${selectedComplaint._id}`, { + status: 'Resolved', + response: responseText + }); + toast.success('Response submitted!'); + setOpenDialog(false); + setResponseText(''); + fetchComplaints(); + } catch (err) { + toast.error('Failed to submit response'); + } + }; + + return ( +
+ {/* Header Section */} +
+
+
+ + +
+
+ + {/* Search and Filter Section */} +
+ setSearchTerm(e.target.value)} + sx={{ + '& .MuiOutlinedInput-root': { + height: 56, + borderRadius: '8px', + '&:hover fieldset': { borderColor: '#641A90' }, + '&.Mui-focused fieldset': { borderColor: '#641A90' } + } + }} + /> + + + Status + + + + +
+
+ + {/* Complaints Table */} + + + + + + User Details + Date + Complaint + Complaint Type + Status + Action + + + + {complaints + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((complaint) => ( + + + + + + + {complaint.user?.name} + + + {complaint.user?.email} + + + + + + +
+ + {new Date(complaint.createdAt).toLocaleDateString()} + + + {new Date(complaint.createdAt).toLocaleTimeString()} + +
+
+ + + {complaint.description} + + + + {complaint.complaintType} + + + + + {complaint.status} + + + + + { + setSelectedComplaint(complaint); + setOpenDialog(true); + }} + > + + + +
+ ))} +
+
+
+ +
+
+ +
+ + {/* Response Dialog */} + setOpenDialog(false)} + maxWidth="md" + fullWidth + PaperProps={{ className: "rounded-lg" }} + > + +
+ Respond to Complaint + + {selectedComplaint && new Date(selectedComplaint.createdAt).toLocaleString()} + +
+
+ + + {selectedComplaint && ( + <> +
+
+ +
+ {selectedComplaint.user?.name} + + {selectedComplaint.user?.email} + +
+
+
+ +
+ + {selectedComplaint.description} + +
+ +
+ Admin Response + setResponseText(e.target.value)} + className="rounded-lg" + /> + + {selectedComplaint.response && ( +
+ + Previous Response + + + {selectedComplaint.response} + +
+ )} +
+ + )} +
+ + + + + +
+
+ ); +}; + +export default Complaints; diff --git a/client/src/Admin/CreateGames.jsx b/client/src/Admin/CreateGames.jsx new file mode 100644 index 0000000..748532a --- /dev/null +++ b/client/src/Admin/CreateGames.jsx @@ -0,0 +1,434 @@ +import React, { useState, useEffect, useRef } from 'react'; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb'; +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles'; +import { Typography } from '@mui/material'; +import theme from '../AtomicComponents/theme'; +import { InputField } from '../AtomicComponents/Inputs/Input'; +import ImageSelector from '../MoleculesComponents/Admin_components/ImageSelector'; +import { cpuCores, cpuThreads, gpuAttributes, ramAttributes } from '../AtomicComponents/ForProductForm/Category'; +import { PrimaryButton } from '../AtomicComponents/Buttons/Buttons'; +import axios from 'axios'; +import { toast } from 'sonner'; +import { useParams, useNavigate } from "react-router-dom"; +import Iconset from "../AtomicComponents/Icons/Iconset"; +import { DashboardLayout } from "@toolpad/core"; + +import ToolpadFixer from "../MoleculesComponents/ToolpadFixer"; + + +const CreateGames = () => { + const { id } = useParams(); + const isEditMode = !!id; + + const navigate = useNavigate(); + const imageSelectorRef = useRef(); + + // Options for dropdowns (reusing existing ones from your product form) + const ramTypeOptions = ramAttributes.type; + const ramSpeedOptions = ramAttributes.speed; + const ramSizeOptions = ramAttributes.size; + const gpuVramOptions = gpuAttributes.gpuVram; + + // Initial state for a game + const initialGameState = { + name: "", + description: "", + image: "", + cpu: { + cores: "", + threads: "", + baseClock: "", + boostClock: "" + }, + gpu: { + series: "", + vramGB: "", + boostClockMHz: "", + cores: "" + }, + ram: { + sizeGB: "", + speedMHz: "", + type: "" + } + }; + + const [game, setGame] = useState(initialGameState); + const [selectedImage, setSelectedImage] = useState(null); + + // Fetch game data if in edit mode + useEffect(() => { + if (isEditMode) { + const fetchGame = async () => { + try { + const res = await axios.get(`http://localhost:8000/api/game/games/${id}`); + if (res.data.success) { + const fetchedGame = res.data.game; + console.log("Fetched Game====================================", fetchedGame); + setGame(fetchedGame); + // Assuming backend returns image URL directly, no need to set selectedImage here + } + } catch (error) { + console.error("Error fetching game:", error); + toast.error("Failed to load game data"); + } + }; + fetchGame(); + } + }, [id]); + + // Handle input changes for top-level fields + const handleInputChange = (field, value) => { + setGame((prevGame) => ({ + ...prevGame, + [field]: value, + })); + }; + + // Handle nested field changes (cpu, gpu, ram) + const handleNestedInputChange = (category, field, value) => { + setGame((prevGame) => ({ + ...prevGame, + [category]: { + ...prevGame[category], + [field]: value, + }, + })); + }; + + // Validate required fields + const validateRequiredFields = (gameData, isEditMode = false) => { + const requiredFields = [ + "name", "description", + "cpu.cores", "cpu.threads", "cpu.baseClock", "cpu.boostClock", + "gpu.series", "gpu.vramGB", "gpu.boostClockMHz", "gpu.cores", + "ram.sizeGB", "ram.speedMHz", "ram.type" + ]; + const missingFields = requiredFields.filter(field => { + if (field.includes(".")) { + const [category, subField] = field.split("."); + return !gameData[category][subField] || gameData[category][subField] === ""; + } + return !gameData[field] || gameData[field] === ""; + }); + + // Special validation for image in add mode + if (!isEditMode && !selectedImage) { + missingFields.push("image"); + } + + // Enforce GHz for CPU clocks and MHz for GPU boost clock + const baseClock = gameData.cpu.baseClock.toString().trim().toLowerCase(); + const boostClock = gameData.cpu.boostClock.toString().trim().toLowerCase(); + const gpuBoostClock = gameData.gpu.boostClockMHz.toString().trim().toLowerCase(); + + if (!baseClock.includes("ghz")) { + setGame(prev => ({ + ...prev, + cpu: { ...prev.cpu, baseClock: `${baseClock} GHz` } + })); + } + if (!boostClock.includes("ghz")) { + setGame(prev => ({ + ...prev, + cpu: { ...prev.cpu, boostClock: `${boostClock} GHz` } + })); + } + if (!gpuBoostClock.includes("mhz")) { + setGame(prev => ({ + ...prev, + gpu: { ...prev.gpu, boostClockMHz: `${gpuBoostClock} MHz` } + })); + } + + if (missingFields.length > 0) { + throw new Error(`Please fill in all required fields: ${missingFields.join(", ")}. CPU clocks must include GHz, GPU boost clock must include MHz.`); + } + }; + + // Handle form submission + const onSubmitHandler = async (e) => { + e.preventDefault(); + try { + const formData = new FormData(); + + if (selectedImage) { + formData.append("image", selectedImage); + } + + // Validate fields + validateRequiredFields(game, isEditMode); + + // Prepare game data for submission (remove image field since it’s handled separately) + const gameData = { ...game }; + delete gameData.image; + delete gameData.imagePublicId; + + formData.append("name", gameData.name); + formData.append("description", gameData.description); + formData.append("cpu", JSON.stringify(gameData.cpu)); + formData.append("gpu", JSON.stringify(gameData.gpu)); + formData.append("ram", JSON.stringify(gameData.ram)); + + const endpoint = isEditMode + ? `http://localhost:8000/api/game/games/${id}` + : `http://localhost:8000/api/game/games`; + + const response = isEditMode + ? await axios.put(endpoint, formData, { + headers: { "Content-Type": "multipart/form-data" } + }) + : await axios.post(endpoint, formData, { + headers: { "Content-Type": "multipart/form-data" } + }); + + if (response.data.success) { + toast.success(isEditMode ? "Game updated successfully" : "Game added successfully"); + if (!isEditMode) { + setGame(initialGameState); + setSelectedImage(null); + if (imageSelectorRef.current) { + imageSelectorRef.current.deleteAllImages(); + } + } + } else { + toast.error(isEditMode ? "Error updating game" : "Error adding game. Please try again."); + } + } catch (error) { + console.error(error); + toast.error(error.message); + } + }; + + return ( +
+ +
+
+
+ +
+
+
+
+
+
+ Details + Name, Description, Image +
+
+
+
+ Name + handleInputChange('name', value)} + value={game.name} + type='text' + label="Game Name" + width='100%' + /> +
+
+ Description + handleInputChange('description', value)} + value={game.description} + type='text' + label="Description" + width='100%' + rows={12} + /> +
+
+ Image + { + setSelectedImage(images[0]); // Only one image for games + setGame((prevGame) => ({ + ...prevGame, + image: images.length > 0 ? URL.createObjectURL(images[0]) : "" + })); + }} + maxImages={1} // Limit to one image + /> +
+
+
+
+
+ System Requirements + CPU, GPU, RAM Specifications +
+
+
+
+ CPU Requirements +
+
+ handleNestedInputChange('cpu', 'cores', value)} + /> +
+
+ handleNestedInputChange('cpu', 'threads', value)} + /> +
+
+ handleNestedInputChange('cpu', 'baseClock', value)} + /> +
+
+ handleNestedInputChange('cpu', 'boostClock', value)} + /> +
+
+
+
+ GPU Requirements +
+
+ handleNestedInputChange('gpu', 'series', value)} + /> +
+
+ handleNestedInputChange('gpu', 'vramGB', value)} + /> +
+
+ handleNestedInputChange('gpu', 'boostClockMHz', value)} + /> +
+
+ handleNestedInputChange('gpu', 'cores', value)} + /> +
+
+
+
+ RAM Requirements +
+
+ handleNestedInputChange('ram', 'sizeGB', value)} + /> +
+
+ handleNestedInputChange('ram', 'speedMHz', value)} + /> +
+
+ handleNestedInputChange('ram', 'type', value)} + /> +
+
+
+
+
+
+
+ {isEditMode && ( + navigate('/games/managegames')} // Adjust route as needed + /> + )} + +
+
+
+
+
+
+
+ ); +}; + +export default CreateGames; \ No newline at end of file diff --git a/client/src/Admin/CreateProducts.jsx b/client/src/Admin/CreateProducts.jsx new file mode 100644 index 0000000..b04db83 --- /dev/null +++ b/client/src/Admin/CreateProducts.jsx @@ -0,0 +1,1010 @@ +import React, { useState, useEffect, useRef } from 'react'; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb'; +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles'; +import { Typography } from '@mui/material'; +import theme from '../AtomicComponents/theme'; +import { InputField } from '../AtomicComponents/Inputs/Input'; +import ImageSelector from '../MoleculesComponents/Admin_components/ImageSelector'; +import { + main, subCategories, coolerAttributes, cpuCores, cpuThreads, gpuAttributes, + ramAttributes, motherboardAttributes, storageAttributes, casingAttributes, + mouseAttributes, keyboardAttributes, monitorAttributes, laptopAttributes, desktopAttributes +} from '../AtomicComponents/ForProductForm/Category'; +import { useSelector, useDispatch } from "react-redux"; +import { setSelectedMainCategory, setSelectedSubCategory, setSelectedManufacture, resetForm } from "../Store/formSlice"; +import { PrimaryButton } from '../AtomicComponents/Buttons/Buttons'; +import axios from 'axios'; +import { toast } from 'sonner'; +import { useParams, useNavigate } from "react-router-dom"; + +const CreateProducts = () => { + const { id } = useParams(); + const isEditMode = !!id; + + const dispatch = useDispatch(); + const navigate = useNavigate(); + const imageSelectorRef = useRef(); + + const { + selectedMainCategory, + selectedSubCategory, + selectedManufacture, + subCategoryOptions, + manufactureOptions, + socketTypeOptions, + } = useSelector((state) => state.form); + + const handleMainCategoryChange = (selectedValue) => { + dispatch(setSelectedMainCategory(selectedValue)); + dispatch(setSelectedSubCategory("")); + dispatch(setSelectedManufacture("")); + setProduct(prev => ({ ...prev, type: "" })); + }; + + const handleSubCategoryChange = (selectedValue) => { + dispatch(setSelectedSubCategory(selectedValue)); + dispatch(setSelectedManufacture("")); + }; + + const handleManufactureChange = (selectedValue) => { + dispatch(setSelectedManufacture(selectedValue)); + setProduct(prev => ({ ...prev, socketType: "" })); + }; + + // Attribute options + const coolerSupportedSockets = coolerAttributes.supportedSocket; + const coolerTypes = coolerAttributes.coolerType; + const ramTypeOptions = ramAttributes.type; + const ramSpeedOptions = ramAttributes.speed; + const ramSizeOptions = ramAttributes.size; + const motherboardChipsets = motherboardAttributes.chipsets; + const motherboardSocket = motherboardAttributes.motherboardSocket; + const motherboardFormFactors = motherboardAttributes.formFactor; + const motherboardRamSlots = motherboardAttributes.ramSlots; + const motherboardMaxRam = motherboardAttributes.maxRam; + const motherboardMemoryTypes = motherboardAttributes.memoryTypes; + const motherboardPcieSlotType = motherboardAttributes.pcieSlotType; + const motherboardPcieVersion = motherboardAttributes.pcieVersion; + const motherboardStorageTypes = motherboardAttributes.storageType; + const motherboardExpansionSlots = motherboardAttributes.expansionSlots; + const gpuInterfaceTypes = gpuAttributes.interfaceType; + const gpuPowerConnectors = gpuAttributes.powerConnectors; + const gpuVramOptions = gpuAttributes.gpuVram; + const gpuSeriesOptions = gpuAttributes.gpuSeries; + const storageTypes = storageAttributes.storageTypes; + const storageCapacities = storageAttributes.storageCapacities; + const casingFormFactors = casingAttributes.formFactor; + const casingSupportedMotherboardSizes = casingAttributes.supportedMotherboardSizes; + const keyboardManufacturerOptions = keyboardAttributes.manufacturer; + const keyboardTypeOptions = keyboardAttributes.type; + const mouseTypeOptions = mouseAttributes.type; + const displaySizeOptions = monitorAttributes.displaySize; + const resolutionOptions = monitorAttributes.resolution; + const refreshRateOptions = monitorAttributes.refreshRate; + const panelTypeOptions = monitorAttributes.panelType; + const monitorTypeOptions = monitorAttributes.monitorType; + const laptopDisplaySizeOptions = laptopAttributes.displaySize; + const laptopResolutionOptions = laptopAttributes.resolution; + const laptopCpuOptions = laptopAttributes.cpu; + const laptopRamOptions = laptopAttributes.ram; + const laptopStorageOptions = laptopAttributes.storage; + const laptopTypeOptions = laptopAttributes.laptopType; + const laptopGraphicCardOptions = laptopAttributes.graphicCard; + const desktopCpuOptions = desktopAttributes.cpu; + const desktopGpuOptions = desktopAttributes.graphicCard; + const desktopRamOptions = desktopAttributes.ram; + const desktopStorageOptions = desktopAttributes.storage; + const desktopTypeOptions = desktopAttributes.desktopType; + + const initialProductState = { + type: "", + name: "", + description: "", + imgUrls: [], + manufacturer: "", + //cpu + socketType: "", + tdp: "", + coreCount: "", + threadCount: "", + baseClock: "", + boostClock: "", + integratedGraphics: "", + includesCooler: "", + //memory + memoryType: "", + memoryCapacity: "", + memorySpeed: "", + //motherboard + chipset: "", + formFactor: "", + ramSlots: "", + maxRam: "", + //laptop & prebuild + displaySize: "", + resolution: "", + laptopType: "", + cpu: "", + ram: "", + storage: "", + graphicCard: "", + desktopType: "", + //gpu + interfaceType: "", + length: "", + powerConnectors: "", + vram: "", + series: "", + cudaCores: "", + //prebuild additional fields + cpuCores: "", + cpuThreads: "", + cpuBaseClock: "", + cpuBoostClock: "", + gpuSeries: "", + gpuVramGB: "", + gpuBoostClockMHz: "", + gpuCores: "", + ramSizeGB: "", + ramSpeedMHz: "", + ramType: "", + quantity: "", + price: "", + }; + + const [product, setProduct] = useState(initialProductState); + const [selectedImages, setSelectedImages] = useState([]); + + useEffect(() => { + if (isEditMode) { + const fetchProduct = async () => { + try { + const res = await axios.get(`http://localhost:8000/api/product/${id}`); + if (res.data.Success) { + const fetchedProduct = res.data.data; + console.log("Fetched Product====================================", fetchedProduct); + setProduct(fetchedProduct); + + let foundMainCategory = null; + for (const [key, categoryList] of Object.entries(subCategories)) { + if (categoryList.some(item => item.value === fetchedProduct.type)) { + foundMainCategory = key; + break; + } + } + + const mainCategoryLabelMap = { + Necessary: "Necessary", + Optional: "Optional", + Common: "Common" + }; + const mainCategoryLabel = mainCategoryLabelMap[foundMainCategory]; + + if (mainCategoryLabel) { + dispatch(setSelectedMainCategory(mainCategoryLabel)); + } + dispatch(setSelectedSubCategory(fetchedProduct.type)); + dispatch(setSelectedManufacture(fetchedProduct.manufacturer)); + } + } catch (error) { + console.error("Error fetching product:", error); + } + }; + fetchProduct(); + } + }, [id, dispatch]); + + useEffect(() => { + setProduct((prevProduct) => ({ + ...prevProduct, + type: selectedSubCategory, + manufacturer: selectedManufacture, + })); + }, [selectedSubCategory, selectedManufacture]); + + const handleInputChange = (field, value) => { + console.log("===================Value", value); + setProduct((prevProduct) => ({ + ...prevProduct, + [field]: typeof prevProduct[field] === 'boolean' ? Boolean(value) : value, + })); + }; + + const getChangedFields = (original, updated) => { + const changed = {}; + for (const key in updated) { + if (Array.isArray(updated[key])) { + if (JSON.stringify(updated[key]) !== JSON.stringify(original[key])) { + changed[key] = updated[key]; + } + } else if (updated[key] !== original[key]) { + changed[key] = updated[key]; + } + } + return changed; + }; + + const onSubmitHandler = async (e) => { + e.preventDefault(); + try { + const formData = new FormData(); + selectedImages.forEach((image, index) => { + formData.append(`image${index + 1}`, image); + }); + + if (product.type === "processor") { + if (!product.includesCooler) product.includesCooler = false; + if (!product.integratedGraphics) product.integratedGraphics = false; + } + + validateRequiredFields(product, isEditMode); + formData.append("product", JSON.stringify(product)); + + const endpoint = isEditMode + ? `http://localhost:8000/api/product/${id}` + : `http://localhost:8000/api/product/add`; + + const response = isEditMode + ? await axios.put(endpoint, formData) + : await axios.post(endpoint, formData); + + if (response.data.Success) { + toast.success(isEditMode ? "Product updated successfully" : "Product created successfully"); + if (!isEditMode) { + setProduct({ ...initialProductState }); + dispatch(resetForm()); + if (imageSelectorRef.current) { + imageSelectorRef.current.deleteAllImages(); + } + } + } else { + toast.error(isEditMode ? "Error in Updating" : "Error creating product. Please try again."); + } + } catch (error) { + console.log(error); + toast.error(error.message); + } + }; + + const validateRequiredFields = (product, isEditMode = false) => { + const allRequiredFields = { + processor: ["name", "price", "description", "imgUrls", "type", "manufacturer", "quantity", "socketType", "tdp", "coreCount", "threadCount", "baseClock", "boostClock", "integratedGraphics", "includesCooler"], + gpu: ["name", "price", "description", "imgUrls", "type", "manufacturer", "quantity", "interfaceType", "tdp", "series", "length", "powerConnectors", "vram", "boostClock", "cudaCores"], + ram: ["name", "price", "description", "imgUrls", "type", "manufacturer", "quantity", "memoryType", "memoryCapacity", "memorySpeed"], + motherboard: ["name", "price", "description", "imgUrls", "type", "manufacturer", "socketType", "chipset", "formFactor", "ramSlots", "maxRam", "memoryType"], + laptop: ["name", "price", "description", "imgUrls", "type", "manufacturer", "quantity", "displaySize", "resolution", "cpu", "ram", "storage", "graphicCard"], + prebuild: [ + "name", "price", "description", "imgUrls", "type", "manufacturer", "quantity", + "cpu", "cpuCores", "cpuThreads", "cpuBaseClock", "cpuBoostClock", + "graphicCard", "gpuSeries", "gpuVramGB", "gpuBoostClockMHz", "gpuCores", + "ramSizeGB", "ramSpeedMHz", "ramType", + "storage", "desktopType" + ], + default: ["name", "price", "description", "imgUrls", "type", "manufacturer", "quantity"], + }; + const requiredFields = allRequiredFields[product.type] || allRequiredFields["default"]; + const missingFields = requiredFields.filter(field => { + if (field === "imgUrls" && isEditMode) return false; + if (field === "imgUrls") { + return product.imgUrls.length === 0; + } + // Special validation for clock speeds in prebuild + if (field === "cpuBaseClock" || field === "cpuBoostClock") { + if (!product[field]) return true; + const value = product[field].toString().trim().toLowerCase(); + if (!value.includes("ghz")) { + setProduct(prev => ({ ...prev, [field]: `${value} GHz` })); + } + return false; + } + if (field === "gpuBoostClockMHz") { + if (!product[field]) return true; + const value = product[field].toString().trim().toLowerCase(); + if (!value.includes("mhz")) { + setProduct(prev => ({ ...prev, [field]: `${value} MHz` })); + } + return false; + } + return product[field] === null || product[field] === ""; + }); + if (missingFields.length > 0) { + throw new Error(`Please fill in all required fields correctly: ${missingFields.join(", ")}. CPU clocks must include GHz, GPU boost clock must include MHz.`); + } + }; + + return ( +
+
+
+ +
+
+
+
+
+
+ Details + Title, Content, Image +
+
+
+
+ Title + handleInputChange('name', value)} + value={product.name} + type='text' + label="Product Name" + width='100%' + /> +
+
+ Content + handleInputChange('description', value)} + value={product.description} + type='text' + label="Description" + width='100%' + rows={12} + /> +
+
+ Images + { + setSelectedImages(images); + setProduct((prevProduct) => ({ + ...prevProduct, + imgUrls: images.map((image) => URL.createObjectURL(image)), + })); + }} + /> +
+
+
+
+
+ Propoties + Additional function and attributes +
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ handleInputChange('quantity', value)} + /> +
+
+ {selectedSubCategory === "processor" && ( +
+
+
+ handleInputChange('socketType', value)} + /> +
+
+ handleInputChange('tdp', value)} + /> +
+
+ handleInputChange('coreCount', value)} + /> +
+
+ handleInputChange('threadCount', value)} + /> +
+
+ handleInputChange('baseClock', value)} + /> +
+
+ handleInputChange('boostClock', value)} + /> +
+
+
+
+ handleInputChange('integratedGraphics', value)} + /> +
+
+ handleInputChange('includesCooler', value)} + /> +
+
+
+ )} + {selectedSubCategory === "motherboard" && ( +
+
+
+ handleInputChange('chipset', value)} + width='100%' + /> +
+
+ handleInputChange('formFactor', value)} + width='100%' + /> +
+
+ handleInputChange('socketType', value)} + width='100%' + /> +
+
+ handleInputChange('ramSlots', parseInt(value) || 0)} + width='100%' + /> +
+
+ handleInputChange('maxRam', parseInt(value) || 0)} + width='100%' + /> +
+
+ handleInputChange('memoryType', value)} + width='100%' + /> +
+
+
+ )} + {selectedSubCategory === "ram" && ( +
+
+
+ handleInputChange('memoryType', value)} + /> +
+
+ handleInputChange('memoryCapacity', parseInt(value) || 0)} + /> +
+
+ handleInputChange('memorySpeed', parseInt(value) || 0)} + /> +
+
+
+ )} + {selectedSubCategory === "gpu" && ( +
+
+
+ handleInputChange('interfaceType', value)} + /> +
+
+ handleInputChange('length', value)} + /> +
+
+ handleInputChange('powerConnectors', value)} + /> +
+
+ handleInputChange('cudaCores', value)} + /> +
+
+ handleInputChange('series', value)} + /> +
+
+ handleInputChange('vram', value)} + /> +
+
+ handleInputChange('tdp', value)} + /> +
+
+ handleInputChange('boostClock', value)} + /> +
+
+
+ )} + {selectedSubCategory === "laptop" && ( +
+
+
+ handleInputChange('displaySize', value)} + /> +
+
+ handleInputChange('resolution', value)} + /> +
+
+ handleInputChange('cpu', value)} + /> +
+
+ handleInputChange('ram', value)} + /> +
+
+ handleInputChange('storage', value)} + /> +
+
+ handleInputChange('laptopType', value)} + /> +
+
+ handleInputChange('graphicCard', value)} + /> +
+
+
+ )} + {selectedSubCategory === "prebuild" && ( +
+
+ {/* CPU Fields */} +
+ handleInputChange('cpu', value)} + /> +
+
+ handleInputChange('cpuCores', value)} + /> +
+
+ handleInputChange('cpuThreads', value)} + /> +
+
+ handleInputChange('cpuBaseClock', value)} + /> +
+
+ handleInputChange('cpuBoostClock', value)} + /> +
+ + {/* GPU Fields */} +
+ handleInputChange('graphicCard', value)} + /> +
+
+ handleInputChange('gpuSeries', value)} + /> +
+
+ handleInputChange('gpuVramGB', value)} + /> +
+
+ handleInputChange('gpuBoostClockMHz', value)} + /> +
+
+ handleInputChange('gpuCores', value)} + /> +
+ + {/* RAM Fields */} +
+ handleInputChange('ramSizeGB', value)} + /> +
+
+ handleInputChange('ramSpeedMHz', value)} + /> +
+
+ handleInputChange('ramType', value)} + /> +
+ + {/* Existing Fields */} +
+ handleInputChange('storage', value)} + /> +
+
+ handleInputChange('desktopType', value)} + /> +
+
+
+ )} +
+
+
+
+ Pricing + Buy and Sale Prices +
+
+
+
+ +
+
+ handleInputChange('price', value)} + /> +
+
+
+
+
+ {isEditMode && ( + navigate('/products/manageproduct')} + /> + )} + +
+
+
+
+
+
+ ); +}; + +export default CreateProducts; \ No newline at end of file diff --git a/client/src/Admin/Dashboard.jsx b/client/src/Admin/Dashboard.jsx new file mode 100644 index 0000000..e74dce7 --- /dev/null +++ b/client/src/Admin/Dashboard.jsx @@ -0,0 +1,11 @@ +import { Typography } from '@mui/material' +import React from 'react' + +export default function Dashboard() { + return ( +
+ Dashboard +
+ ) +} + diff --git a/client/src/Admin/InvoiceCreate.jsx b/client/src/Admin/InvoiceCreate.jsx new file mode 100644 index 0000000..3efea18 --- /dev/null +++ b/client/src/Admin/InvoiceCreate.jsx @@ -0,0 +1,255 @@ +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import CustomBreadcrumbs from "../AtomicComponents/Breadcrumb"; +import { PageTitle } from "../AtomicComponents/Typographics/TextStyles"; +import { AddButton } from "../AtomicComponents/Buttons/Buttons"; +import { InputField } from "../AtomicComponents/Inputs/Input"; +import { + StockType, + main, + InvoiceStatus, +} from "../AtomicComponents/ForAdminForms/Category"; +import SetDate from "../AtomicComponents/Inputs/date"; +import { SearchBar } from "../AtomicComponents/Inputs/Searchbar"; +import { Divider, IconButton, TextField, Button } from "@mui/material"; +import { Add, RemoveCircle } from "@mui/icons-material"; +import Iconset from "../AtomicComponents/Icons/Iconset.jsx"; + +function InvoiceCreate() { + const navigate = useNavigate(); + + const [fromEdit, setFromEdit] = useState(false); + const [toEdit, setToEdit] = useState(false); + const [fromAddress, setFromAddress] = useState(""); + const [toAddress, setToAddress] = useState(""); + const [items, setItems] = useState([ + { + itemCode: "", + itemName: "", + subCategory: "", + quantity: 1, + price: "0", + }, + ]); + + const handleItemChange = (index, key, value) => { + const updatedItems = [...items]; + updatedItems[index][key] = value; + setItems(updatedItems); + }; + + const addItem = () => { + setItems([ + ...items, + { + itemCode: "", + itemName: "", + subCategory: "", + quantity: 1, + price: "0", + }, + ]); + }; + + const removeItem = (index) => { + const updatedItems = [...items]; + updatedItems.splice(index, 1); + setItems(updatedItems); + }; + + return ( +
+
+ + +
+
+
+
+
+

From:

+ setFromEdit(!fromEdit)} size="small"> + + +
+ {fromEdit ? ( +
+ + setFromEdit(false)} + /> +
+ ) : fromAddress ? ( +

{fromAddress}

+ ) : ( +

No address added.

+ )} +
+ + + +
+
+

To:

+ setToEdit(!toEdit)} size="small"> + + +
+ {toEdit ? ( +
+ + setToEdit(false)} + /> +
+ ) : toAddress ? ( +

{toAddress}

+ ) : ( +

No address added.

+ )} +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

Details:

+ {items.map((item, index) => ( +
+ handleItemChange(index, "itemCode", val)} + /> +
+

Item Name

+ + handleItemChange(index, "itemName", e.target.value) + } + /> +
+ + handleItemChange(index, "subCategory", val) + } + /> + handleItemChange(index, "quantity", val)} + /> + handleItemChange(index, "price", val)} + /> + {items.length > 1 && ( +
+ +
+ )} +
+ ))} + +
+
+
+ +
+
+ navigate("/invoice/invoicecreate")} + /> +
+
+
+ ); +} + +export default InvoiceCreate; diff --git a/client/src/Admin/InvoiceList.jsx b/client/src/Admin/InvoiceList.jsx new file mode 100644 index 0000000..a3aff3a --- /dev/null +++ b/client/src/Admin/InvoiceList.jsx @@ -0,0 +1,105 @@ +import React from "react"; +import { useNavigate } from "react-router-dom"; +import { UserTable } from "../MoleculesComponents/Table"; +import CustomerCard from "../AtomicComponents/Cards/Customercard"; +import TimeCard from "../AtomicComponents/Cards/TimeCard"; +import CustomBreadcrumbs from "../AtomicComponents/Breadcrumb"; +import { PageTitle } from "../AtomicComponents/Typographics/TextStyles"; +import { AddButton } from "../AtomicComponents/Buttons/Buttons"; +import { InputField } from "../AtomicComponents/Inputs/Input"; +import { StockType, main } from "../AtomicComponents/ForAdminForms/Category"; +import SetDate from "../AtomicComponents/Inputs/date"; +import { SearchBar } from "../AtomicComponents/Inputs/Searchbar"; +import ToolpadFixer from "../MoleculesComponents/ToolpadFixer"; + +function InvoiceList() { + const navigate = useNavigate(); + + const invoiceColumns = [ + { id: "customerCard", label: "Customer" }, + { id: "startdate", label: "Created" }, + { id: "enddate", label: "Due" }, + { id: "amount", label: "Amount" }, + ]; + + const invoiceData = [ + { + customerCard: ( + + ), + startdate: , + enddate: , + amount: "720,000 LKR", + }, + ]; + + const iconTypes = ["view", "edit", "delete"]; + + return ( +
+ +
+
+
+ + +
+ +
+
+ navigate("/invoice/invoicecreate")} + /> +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+
+ ); +} + +export default InvoiceList; diff --git a/client/src/Admin/Layout.jsx b/client/src/Admin/Layout.jsx new file mode 100644 index 0000000..fb8cfe0 --- /dev/null +++ b/client/src/Admin/Layout.jsx @@ -0,0 +1,12 @@ +import { DashboardLayout } from '@toolpad/core'; +import { Outlet } from 'react-router-dom'; +import AccountDropdown from '../MoleculesComponents/Admin_components/AccountDropdown'; + +export default function Layout() { + return ( + + + + ) +} + diff --git a/client/src/Admin/ManageGames.jsx b/client/src/Admin/ManageGames.jsx new file mode 100644 index 0000000..84111e1 --- /dev/null +++ b/client/src/Admin/ManageGames.jsx @@ -0,0 +1,204 @@ +import React, { useEffect, useState } from "react"; +import axios from "axios"; +import { toast } from "sonner"; +import { useNavigate } from "react-router-dom"; +import { UserTable } from "../MoleculesComponents/Table"; +import ProductCard from "../AtomicComponents/Cards/Productcard"; +import TimeCard from "../AtomicComponents/Cards/TimeCard"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb'; +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles'; +import { AddButton } from "../AtomicComponents/Buttons/Buttons"; +import { SearchBar } from "../AtomicComponents/Inputs/Searchbar"; +import DialogAlert from "../AtomicComponents/Dialogs/Dialogs"; +import Iconset from "../AtomicComponents/Icons/Iconset"; +import { DashboardLayout } from "@toolpad/core"; +import theme from '../AtomicComponents/theme'; +import ToolpadFixer from "../MoleculesComponents/ToolpadFixer"; + + + + + + + + + + + +function ManageGames() { + const [games, setGames] = useState([]); + const [filteredGames, setFilteredGames] = useState([]); + const [searchTerm, setSearchTerm] = useState(''); + const [openDialog, setOpenDialog] = useState(false); + const [selectedGameId, setSelectedGameId] = useState(null); + + const navigate = useNavigate(); + + useEffect(() => { + fetchGames(); + }, []); + + useEffect(() => { + applyFilters(); + }, [searchTerm, games]); + + const fetchGames = async (searchTerm = "") => { + try { + const response = await axios.get("http://localhost:8000/api/game/games", { + params: searchTerm ? { search: searchTerm } : {} + }); + + console.log("API Response:", response.data); + + if (response.data && Array.isArray(response.data.games)) { + const allGames = response.data.games; + setGames(allGames); + applyFilters(allGames); + } else { + console.error("Expected an array but got:", response.data); + setGames([]); + setFilteredGames([]); + } + } catch (error) { + console.error("Error fetching games:", error); + setGames([]); + setFilteredGames([]); + toast.error("Failed to fetch games"); + } + }; + + const applyFilters = (allGames = games) => { + let filtered = allGames; + + if (searchTerm) { + filtered = filtered.filter(game => + game.name.toLowerCase().includes(searchTerm.toLowerCase()) || + game.description.toLowerCase().includes(searchTerm.toLowerCase()) + ); + } + + setFilteredGames(filtered); + }; + + const handleEdit = (id) => { + navigate(`/games/creategame/${id}`); + }; + + const handleDelete = async () => { + try { + const response = await axios.delete(`http://localhost:8000/api/game/games/${selectedGameId}`); + if (response.data.success) { + toast.success("Game deleted successfully"); + fetchGames(); + } else { + toast.error(response.data.message); + } + } catch (error) { + toast.error("Failed to delete game"); + } + setOpenDialog(false); + }; + + const openDeleteDialog = (_id) => { + console.log("Delete game ID:", _id); + setSelectedGameId(_id); + setOpenDialog(true); + }; + + const gameColumns = [ + { id: "gameCard", label: "Game" }, + { id: "date", label: "Added On" }, + { id: "cpu", label: "CPU Requirements" }, + { id: "gpu", label: "GPU Requirements" }, + { id: "ram", label: "RAM Requirements" }, + ]; + + const gameData = Array.isArray(filteredGames) + ? filteredGames.map(game => ({ + id: game._id, + gameCard: , + date: , + cpu: `${game.cpu.cores} Cores, ${game.cpu.threads} Threads, ${game.cpu.baseClock} - ${game.cpu.boostClock}`, + gpu: `${game.gpu.series}, ${game.gpu.vramGB} GB VRAM, ${game.gpu.boostClockMHz}`, + ram: `${game.ram.sizeGB} GB, ${game.ram.speedMHz} MHz, ${game.ram.type}`, + })) + : []; + + const iconTypes = ["edit", "delete"]; + const iconActions = { + edit: (_id) => handleEdit(_id), + delete: (_id) => openDeleteDialog(_id), + }; + + return ( +
+ +
+
+ {/* Header Section */} +
+ + +
+ + {/* Button Section */} +
+ navigate('/games/creategame')} + /> +
+ + {/* Table and Filter Section */} +
+
+
+
+ { + setSearchTerm(e.target.value); + fetchGames(e.target.value); + }} + /> +
+
+
+
+ +
+
+ + {/* Delete Confirmation Dialog */} + setOpenDialog(false)} + handleAgree={handleDelete} + /> +
+
+
+ ); +} + +export default ManageGames; \ No newline at end of file diff --git a/client/src/Admin/ManageProducts.jsx b/client/src/Admin/ManageProducts.jsx new file mode 100644 index 0000000..967d3f0 --- /dev/null +++ b/client/src/Admin/ManageProducts.jsx @@ -0,0 +1,292 @@ +import React from "react"; +import { useEffect, useState } from "react"; +import axios from "axios"; +import { toast } from "sonner"; +import { useNavigate } from "react-router-dom"; +import { UserTable } from "../MoleculesComponents/Table"; +import ProductCard from "../AtomicComponents/Cards/Productcard"; +import TimeCard from "../AtomicComponents/Cards/TimeCard"; +import QuantityCard from "../AtomicComponents/Cards/QuantityCard"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' +import { AddButton, PrimaryButton } from "../AtomicComponents/Buttons/Buttons"; +import { InputField } from "../AtomicComponents/Inputs/Input"; +import { StockType, main, subCategories } from '../AtomicComponents/ForProductForm/Category'; +import SetDate from "../AtomicComponents/Inputs/date"; +import { SearchBar } from "../AtomicComponents/Inputs/Searchbar"; +import { useSelector, useDispatch } from "react-redux"; +import { setSelectedMainCategory, setSelectedSubCategory } from "../Store/formSlice"; +import StatusCard from "../AtomicComponents/Cards/StatusCard"; +import DialogAlert from "../AtomicComponents/Dialogs/Dialogs"; + +function ManageProducts() { + + const [products, setProducts] = useState([]); + const [filteredProducts, setFilteredProducts] = useState([]); + const [searchTerm, setSearchTerm] = useState(''); + const [statusFilter, setStatusFilter] = useState(''); + const [selectedDate, setSelectedDate] = useState(null); + const [openDialog, setOpenDialog] = useState(false); + const [selectedProductId, setSelectedProductId] = useState(null); + + const navigate = useNavigate(); + const dispatch = useDispatch(); + + const { + selectedMainCategory, + subCategoryOptions, + selectedSubCategory, + } = useSelector((state) => state.form); + + const handleMainCategoryChange = (selectedValue) => { + dispatch(setSelectedMainCategory(selectedValue)); + dispatch(setSelectedSubCategory('')); + }; + + const handleSubCategoryChange = (selectedValue) => { + dispatch(setSelectedSubCategory(selectedValue)); + applyFilters(products, selectedValue); + }; + + + const handleInputChange = (field, value) => { + if (field === 'statusFilter') { + setStatusFilter(value); + } + // Add more fields if needed + }; + + useEffect(() => { + fetchProducts(); + }, []); + + useEffect(() => { + applyFilters(); + }, [statusFilter, selectedSubCategory, products, selectedDate]); + + const fetchProducts = async (searchTerm = "") => { + try { + const response = await axios.get("http://localhost:8000/api/product/all", { + params: searchTerm ? { search: searchTerm } : {} + }); + + console.log("API Response:", response.data); + + if (response.data && Array.isArray(response.data.data)) { + const allProducts = response.data.data; + setProducts(allProducts); + applyFilters(allProducts); + } else { + console.error("Expected an array but got:", response.data); + setProducts([]); + setFilteredProducts([]); + } + } catch (error) { + console.error("Error fetching products:", error); + setProducts([]); + setFilteredProducts([]); + toast.error("Failed to fetch products"); + } + }; + + const applyFilters = (allProducts = products, selectedType = selectedSubCategory) => { + let filtered = allProducts; + + // Filter by stock status + if (statusFilter) { + filtered = filtered.filter(product => { + if (statusFilter === "In Stock") return product.quantity > 5; + if (statusFilter === "Low Stock") return product.quantity > 0 && product.quantity <= 5; + if (statusFilter === "Out of Stock") return product.quantity === 0; + return true; + }); + } + + // Filter by subcategory options + if (selectedType) { + filtered = filtered.filter(product => product.type === selectedType); + } + + // Filter by Date + if (selectedDate) { + filtered = filtered.filter(product => { + const productDate = new Date(product.createdAt).toLocaleDateString(); + const selectedFormatted = new Date(selectedDate).toLocaleDateString(); + return productDate === selectedFormatted; + }); + } + + setFilteredProducts(filtered); + }; + + const handleEdit = (id) => { + navigate(`/products/createproduct/${id}`); + }; + + const handleDelete = async () => { + try { + console.log("funtion=================", selectedProductId) + const response = await axios.delete(`http://localhost:8000/api/product/${selectedProductId}`); + if (response.data.Success) { + toast.success("Product deleted successfully", selectedProductId); + fetchProducts(); + } else { + toast.error(response.data.message); + } + } catch (error) { + toast.error("Failed to delete product"); + } + setOpenDialog(false); + }; + + const openDeleteDialog = (_id) => { + console.log("Delete product ID:", _id); + setSelectedProductId(_id); + setOpenDialog(true); + }; + + const productColumns = [ + { id: "productCard", label: "Product" }, + { id: "date", label: "Created at" }, + { id: "availability", label: "Stock Availability" }, + { id: "quantity", label: "Quantity" }, + { id: "stock", label: "Stock Value" }, + ]; + + const getCategoryLabel = (type) => { + for (const category in subCategories) { + const found = subCategories[category].find(item => item.value === type); + if (found) return found.label; + } + }; + + const productData = Array.isArray(filteredProducts) + ? filteredProducts.map(product => ({ + id: product._id, + productCard: , + date: , + availability: 5 ? "In Stock" : product.quantity <= 5 && product.quantity > 0 ? "Low Stock" : "Out of Stock"} />, + quantity: < QuantityCard quantity={product.quantity} unitprice={`Unit Price - ${product.price}`} />, + stock: `${product.quantity * product.price} LKR`, + })) + : []; + + const iconTypes = ["view", "edit", "delete"]; + const iconActions = { + // view: handleView, + edit: (_id) => handleEdit(_id), + delete: (_id) => { + openDeleteDialog(_id); + } + }; + + + + return ( +
+
+ + +
+ +
+
+ navigate('/products/createproduct')} + /> +
+ +
+ + +
+
+
+
+ handleInputChange('statusFilter', value)} + width='100%' + /> +
+
+ setSelectedDate(date)} + > + +
+
+ +
+
+ handleSubCategoryChange(value)} + width='100%' + /> +
+
+ { + setSearchTerm(e.target.value); + fetchProducts(e.target.value); + }} + > + +
+
+
+
+ +
+
+ setOpenDialog(false)} + handleAgree={handleDelete} + /> +
+ + ); +}; + +export default ManageProducts diff --git a/client/src/Admin/RMA.jsx b/client/src/Admin/RMA.jsx new file mode 100644 index 0000000..b2057e1 --- /dev/null +++ b/client/src/Admin/RMA.jsx @@ -0,0 +1,255 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + Box, + Typography, + TextField, + Button, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Select, + MenuItem, + InputLabel, + FormControl, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + CircularProgress +} from '@mui/material'; +import ReplyIcon from '@mui/icons-material/Reply'; +import { toast } from 'sonner'; +import { format } from 'date-fns'; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' + +const RMA = () => { + const [requests, setRequests] = useState([]); + const [loading, setLoading] = useState(true); + const [filters, setFilters] = useState({ + orderId: '', + status: '' + }); + const [selectedRequest, setSelectedRequest] = useState(null); + const [responseText, setResponseText] = useState(''); + const [openDialog, setOpenDialog] = useState(false); + + const fetchRequests = async () => { + try { + setLoading(true); + const response = await axios.get('http://localhost:8000/api/rma/admin/requests', { + params: filters, + headers: { + Authorization: `Bearer ${localStorage.getItem('accessToken')}` + } + }); + + // Ensure response is always an array + const data = Array.isArray(response?.data) ? response.data : []; + setRequests(data); + + } catch (error) { + console.error('Fetch Error:', error); + toast.error('Failed to load requests'); + setRequests([]); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchRequests(); + }, [filters]); + + const handleResponseSubmit = async () => { + try { + await axios.put(`http://localhost:8000/api/rma/admin/respond/${selectedRequest?._id}`, { + status: 'Resolved', + response: responseText + }, { + headers: { + Authorization: `Bearer ${localStorage.getItem('accessToken')}` + } + }); + toast.success('Response submitted successfully'); + setOpenDialog(false); + fetchRequests(); + } catch (error) { + toast.error('Failed to submit response'); + } + }; + + const statusColors = { + Processing: 'bg-blue-100 text-blue-800', + Resolved: 'bg-green-100 text-green-800', + Pending: 'bg-yellow-100 text-yellow-800' + }; + + return ( + +
+ + +
+ + {/* Search Filters */} + + setFilters(prev => ({ ...prev, orderId: e.target.value }))} + size="small" + sx={{ flex: 1 }} + /> + + Status + + + + + + {/* Requests Table */} + + + + + Order ID + Subject + Reason + Status + Created Date + Action + + + + {loading ? ( + + + + Loading requests... + + + ) : requests.length === 0 ? ( + + + + No RMA requests found + + + + ) : ( + requests.map((request) => ( + + {request.orderId} + {request.subject} + {request.reason} + + + {request.status} + + + + {format(new Date(request.createdAt), 'MMM dd, yyyy HH:mm')} + + + { + setSelectedRequest(request); + setOpenDialog(true); + }} + sx={{ color: '#641A90' }} + > + + + + + )) + )} + +
+
+ + {/* Response Dialog */} + setOpenDialog(false)} fullWidth maxWidth="md"> + + Manage RMA Request - {selectedRequest?.orderId} + + + {selectedRequest && ( + + + Subject: + {selectedRequest.subject} + + + Reason: + {selectedRequest.reason} + + + Message: + + {selectedRequest.message} + + + setResponseText(e.target.value)} + sx={{ mt: 2 }} + /> + + )} + + + + + + +
+ ); +}; + +export default RMA; \ No newline at end of file diff --git a/client/src/Admin/Review.jsx b/client/src/Admin/Review.jsx new file mode 100644 index 0000000..c3a8551 --- /dev/null +++ b/client/src/Admin/Review.jsx @@ -0,0 +1,358 @@ +import { useEffect, useState } from "react"; +import axios from "axios"; +import { Bar } from "react-chartjs-2"; +import "chart.js/auto"; +import { + Avatar, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Button, + TextField, + Select, + MenuItem, + InputLabel, + FormControl +} from '@mui/material'; +import { + Person as PersonIcon, + Star as StarIcon, + People as PeopleIcon, + BarChart as BarChartIcon, + Send as SendIcon, + Mail as MailIcon +} from '@mui/icons-material'; +import { toast } from 'sonner'; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb' +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' + +const Review = () => { + const [reviews, setReviews] = useState([]); + const [filter, setFilter] = useState({ + type: "", + date: "", + itemId: "", + minRating: "", + maxRating: "", + }); + const [response, setResponse] = useState({}); + const [stats, setStats] = useState({ + totalReviews: 0, + ratingCounts: [0, 0, 0, 0, 0], + avgRating: 0, + }); + const [openDialog, setOpenDialog] = useState(false); + const [currentReviewId, setCurrentReviewId] = useState(null); + + useEffect(() => { + fetchReviews(); + }, [filter]); // Fetch reviews whenever the filter changes + + const fetchReviews = async () => { + try { + // Filter out empty values before appending to the URL + const filteredParams = Object.fromEntries( + Object.entries(filter).filter(([_, v]) => v) // Only include non-empty values + ); + const queryParams = new URLSearchParams(filteredParams).toString(); + const { data } = await axios.get( + `http://localhost:8000/api/review/admin?${queryParams}` + ); + setReviews(data); + calculateStats(data); + } catch (error) { + console.error("Error fetching reviews", error); + } + }; + + const calculateStats = (reviews) => { + const totalReviews = reviews.length; + const ratingCounts = [0, 0, 0, 0, 0]; + reviews.forEach((review) => { + ratingCounts[review.rating - 1]++; + }); + + const avgRating = + totalReviews > 0 + ? (reviews.reduce((sum, review) => sum + review.rating, 0) / + totalReviews).toFixed(1) + : "0.0"; + setStats({ totalReviews, ratingCounts, avgRating }); + }; + + const handleResponseChange = (reviewId, value) => { + setResponse({ + ...response, + [reviewId]: value, + }); + }; + + const handleResponseSubmit = async (reviewId) => { + try { + await axios.post( + `http://localhost:8000/api/review/admin/respond/${reviewId}`, + { response: response[reviewId] } + ); + fetchReviews(); // Fetch updated reviews after submitting the response + toast.success("Response submitted successfully!"); + handleDialogClose(); + } catch (error) { + console.error("Error responding to review", error); + toast.error("Failed to submit the response."); + } + }; + + const handleDialogOpen = (reviewId) => { + setCurrentReviewId(reviewId); + setOpenDialog(true); + }; + + const handleDialogClose = () => { + setOpenDialog(false); + setCurrentReviewId(null); + setResponse({}); + }; + + return ( +
+
+
+ + +
+ + {/* Filter Section */} + {/* Filter Section */} +
+ + setFilter({ ...filter, type: e.target.value })} + /> + + + + + setFilter({ ...filter, date: e.target.value })} + /> + + + + Rating Filter + + + + +
+ + {/* Stats Cards */} +
+
+
+
+ +
+
+

Total Reviews

+

{stats.totalReviews}

+
+
+
+ +
+
+
+ +
+
+

Average Rating

+

+ {stats.avgRating} + +

+
+
+
+ +
+
+
+ +
+

Rating Distribution

+
+ +
+
+ + {/* Reviews List */} +
+ {reviews.map((review) => ( +
+
+ + {!review.userId?.profilePicture && } + + +
+
+

+ {review.userId?.name || "Anonymous"} + + {Array(review.rating).fill()} + +

+ + {review.type} + + +
+

{review.comment}

+ + {new Date(review.createdAt).toLocaleDateString()} + +
+ + +
+
+
+
+ ))} +
+ + {/* Response Dialog */} + {/* Response Dialog */} + + +
+ + Write Response +
+
+ + handleResponseChange(currentReviewId, e.target.value)} + /> +
+ + + {reviews.find(r => r._id === currentReviewId)?.userId?.email} + +
+
+ + + + +
+
+
+ ); +}; + +export default Review; diff --git a/client/src/Admin/Usermanage.jsx b/client/src/Admin/Usermanage.jsx new file mode 100644 index 0000000..34cd9be --- /dev/null +++ b/client/src/Admin/Usermanage.jsx @@ -0,0 +1,425 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; +import { toast } from "sonner"; +import { + Table, TableBody, TableCell, TableContainer, TableHead, TableRow, + Paper, TextField, Select, MenuItem, Button, IconButton, + Dialog, DialogActions, DialogContent, DialogTitle, Box, Typography, Avatar, TablePagination +} from "@mui/material"; +import { Edit, Delete } from "@mui/icons-material"; +import CustomBreadcrumbs from '../AtomicComponents/Breadcrumb'; +import { PageTitle } from '../AtomicComponents/Typographics/TextStyles' + +const Usermanage = () => { + const [users, setUsers] = useState([]); + const [filteredUsers, setFilteredUsers] = useState([]); + const [editingUser, setEditingUser] = useState(null); + const [isEditing, setIsEditing] = useState(false); + const [formData, setFormData] = useState({ name: "", email: "", Role: "user", password: "" }); + const [filters, setFilters] = useState({ name: "", email: "", Role: "" }); + const [openModal, setOpenModal] = useState(false); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); + const [userToDelete, setUserToDelete] = useState(null); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + + useEffect(() => { + fetchUsers(); + }, []); + + const fetchUsers = () => { + axios.get("http://localhost:8000/api/v1/users") + .then((res) => { + setUsers(res.data); + setFilteredUsers(res.data); + }) + .catch(() => toast.error("Error fetching users")); + }; + + const handleSearch = () => { + const filtered = users.filter(user => { + const nameMatch = user.name.toLowerCase().includes(filters.name.toLowerCase()); + const emailMatch = user.email.toLowerCase().includes(filters.email.toLowerCase()); + const roleMatch = filters.Role ? user.Role === filters.Role : true; + return nameMatch && emailMatch && roleMatch; + }); + setFilteredUsers(filtered); + }; + + const handleFilterChange = (e) => { + setFilters({ ...filters, [e.target.name]: e.target.value }); + }; + + const deleteUser = () => { + if (userToDelete) { + axios.delete(`http://localhost:8000/api/v1/users/${userToDelete._id}`) + .then(() => { + setUsers(users.filter(user => user._id !== userToDelete._id)); + setFilteredUsers(filteredUsers.filter(user => user._id !== userToDelete._id)); + toast.success("User deleted"); + setOpenDeleteDialog(false); + }) + .catch(() => { + toast.error("Error deleting user"); + setOpenDeleteDialog(false); + }); + } + }; + + const startEditing = (user) => { + setEditingUser(user._id); + setIsEditing(true); + setFormData({ name: user.name, email: user.email, Role: user.Role, password: "" }); + setOpenModal(true); + }; + + const saveUser = () => { + if (isEditing) { + axios.put(`http://localhost:8000/api/v1/users/${editingUser}`, formData) + .then(() => { + toast.success("User updated successfully"); + fetchUsers(); + setOpenModal(false); + }) + .catch(() => toast.error("Error updating user")); + } else { + axios.post("http://localhost:8000/api/v1/users", formData) + .then(() => { + toast.success("User added successfully"); + fetchUsers(); + setOpenModal(false); + }) + .catch(() => toast.error("Error adding user")); + } + }; + + const handleAddNewUser = () => { + setIsEditing(false); + setFormData({ name: "", email: "", Role: "user", password: "" }); + setOpenModal(true); + }; + + const openDeleteConfirmationDialog = (user) => { + setUserToDelete(user); + setOpenDeleteDialog(true); + }; + + const closeDeleteConfirmationDialog = () => { + setOpenDeleteDialog(false); + setUserToDelete(null); + }; + + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + return ( +
+

User Management

+
+ + + + +
+ +
+ + +
+ + +
+ + {/* Search/Filters Section */} + + + + + + + + + + + + + + + + Name + Email + Role + Actions + + + + {filteredUsers.length > 0 ? ( + filteredUsers.map((user) => ( + + {user.name} + {user.email} + + + + + startEditing(user)} + style={{ + color: "#641A90", // Purple color + padding: "8px", // Slightly reduced padding + }} + > + {/* Adjust icon size */} + + deleteUser(user._id)} + style={{ + color: "#641A90", + padding: "8px", + }} + > + + + + + )) + ) : ( + + + No matching users found + + + )} + +
+
+ + {/* Pagination */} + +
+ + {/* Edit/Add User Dialog */} + setOpenModal(false)}> + {isEditing ? "Edit User" : "Add New User"} + + setFormData({ ...formData, name: e.target.value })} + sx={{ mb: 2 }} + /> + setFormData({ ...formData, email: e.target.value })} + sx={{ mb: 2 }} + /> + + setFormData({ ...formData, password: e.target.value })} + sx={{ mb: 2 }} + /> + + + + + + + + {/* Delete Confirmation Dialog */} + + Confirm Deletion + + Are you sure you want to delete this user? + + + + + + +
+
+ ); +} + + +export default Usermanage; \ No newline at end of file diff --git a/client/src/App.jsx b/client/src/App.jsx index f67355a..dd975b5 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,35 +1,173 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' -import './App.css' +import { Outlet } from "react-router-dom"; +import { AppProvider } from "@toolpad/core/react-router-dom"; +import Iconset from './AtomicComponents/Icons/Iconset'; +import theme from './AtomicComponents/theme'; + +const NAVIGATION = [ + { + kind: 'header', + title: 'Main', + }, + { + segment: 'dashboard', + title: 'Dashboard', + icon: , + }, + { + segment: 'admin', + title: 'Admin', + icon: , + children: [ + { + segment: 'profile', + title: 'Profile', + icon: , + }, + { + segment: 'setting', + title: 'Settings', + + icon: , + }, + ], + }, + { + kind: 'divider', + }, + { + kind: 'header', + title: 'Product & Order', + }, + { + segment: 'products', + title: 'Products', + icon: , + children: [ + { + segment: 'manageproduct', + title: 'Manage Product', + icon: , + }, + { + segment: 'createproduct', + title: 'Create Product', + icon: , + }, + ], + + }, + { + segment: 'orders', + title: 'Orders ', + icon: , + children: [ + { + segment: 'orderlist', + title: 'Order List', + icon: , + }, + { + segment: 'receiveorder', + title: 'Received Order', + icon: , + }, + ], + }, + { + kind: 'divider', + }, + { + kind: 'header', + title: 'User Section', + }, + { + segment: 'usermanage', + title: 'User Manage', + icon: , + + }, + { + kind: 'divider', + }, + { + kind: 'header', + title: 'Feedbacks', + }, + { + segment: 'feedbackmanage', + title: 'Feedback Manage', + icon: , + children: [ + { + segment: 'complaints', + title: 'Complaints', + icon: , + }, + { + segment: 'comments&reviews', + title: 'Comments & Reviews', + icon: , + }, + { + segment: 'rma', + title: 'RMA', + icon: , + } + ], + }, + { + kind: 'divider', + }, + { + kind: 'header', + title: 'Invoices', + }, + { + segment: 'invoice', + title: 'Invoice ', + icon: , + children: [ + { + segment: 'invoicelist', + title: 'Invoice List', + icon: , + }, + { + segment: 'invoicecreate', + title: 'Create Invoice', + icon: , + }, + ], + }, + +]; function App() { - const [count, setCount] = useState(0) return ( - <> - -

Vite + React

-
- -

- Edit src/App.jsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- + + ), + title: '', + }} + theme={theme} + > + + ) + } -export default App +export default App; diff --git a/client/src/AtomicComponents/Breadcrumb.jsx b/client/src/AtomicComponents/Breadcrumb.jsx new file mode 100644 index 0000000..d617ce5 --- /dev/null +++ b/client/src/AtomicComponents/Breadcrumb.jsx @@ -0,0 +1,41 @@ +import React from "react"; +import { styled } from "@mui/material/styles"; +import theme from "./theme"; + +const BreadcrumbLink = styled("a")(({ theme }) => ({ + textDecoration: "none", + transition: "color 0.3s ease-in-out", + "&:hover": { + color: theme.palette.primary700.main, // Uses primary700 for hover effect + }, +})); + +const BreadcrumbText = styled("span")(({ theme }) => ({ + color: theme.palette.primary.main, +})); + +export default function CustomBreadcrumbs({ paths }) { + + return ( + + ); +} diff --git a/client/src/AtomicComponents/Buttons/Buttons.jsx b/client/src/AtomicComponents/Buttons/Buttons.jsx new file mode 100644 index 0000000..2c30960 --- /dev/null +++ b/client/src/AtomicComponents/Buttons/Buttons.jsx @@ -0,0 +1,389 @@ +import * as React from 'react'; +import Button from '@mui/material/Button'; +import { styled } from '@mui/material/styles'; +import CloudUploadIcon from '@mui/icons-material/CloudUpload'; +import Add from '@mui/icons-material/Add'; + + +//Button Size initilization +const Button_Config = { + small: { + padding: '8px 16px', + fixedWidth: '170px', + }, + medium: { + padding: '14px 18px', + fixedWidth: '180px', + }, + long: { + padding: '12px 28px', + fixedWidth: '250px', + }, + large: { + padding: '16px 40px', + fixedWidth: '320px', + } + +} + +//Common Styles for all buttons +const BaseButton = styled(Button)({ + textTransform: 'none', + borderRadius: 8, + borderWidth: '3px', +}); + +//PrimaryButton + +export function PrimaryButton({ + name, + color, + isBold, + isFixed, + buttonSize, + fontSize, + isRounded, + padding, + onClick, + loading = false, + isDisabled = false, + type +}) { + const sizeConfig = Button_Config[buttonSize] || Button_Config.medium; //set Button Size + const borderRadius = isRounded ? '30px' : '8px'; //set rounded Border + + return ( +
+ + {name} + +
+ + ); +} + +//OutlinedButton +export function OutlinedButton({ + name, + color, + isBold, + isFixed, + buttonSize, + fontSize, + isRounded, + onClick, + loading = false, + isDisabled = false, + type +}) { + const sizeConfig = Button_Config[buttonSize] || Button_Config.medium; //set Button Size + const borderRadius = isRounded ? '30px' : '8px'; //set rounded Border + return ( +
+ + {name} + +
+ + ); +} + +//TextButton +export function TextButton({ + name, + color, + isBold, + isFixed, + buttonSize, + fontSize, + isRounded, + onClick, + loading = false, + isDisabled = false, + type +}) { + const sizeConfig = Button_Config[buttonSize] || Button_Config.medium; //set Button Size + const borderRadius = isRounded ? '30px' : '8px'; //set rounded Border + + return ( +
+ + {name} + +
+ + ); +} + +//CustomOutlinedButton +export function CustomOutlinedButton({ + name, + isBold, + isFixed, + buttonSize, + fontSize, + onClick, + loading = false, + isDisabled = false, + type +}) { + const sizeConfig = Button_Config[buttonSize] || Button_Config.medium; //set Button Size + return ( +
+ + {name} + +
+ ); +} + +//Apply Button +export function ApplyButton({ + loading = false, + isDisabled = false, + onClick, + type +}) { + return ( +
+ + Apply + +
+ ); +} + +//Upload Button + +const VisuallyHiddenInput = styled('input')({ + clip: 'rect(0 0 0 0)', + clipPath: 'inset(50%)', + height: 1, + overflow: 'hidden', + position: 'absolute', + bottom: 0, + left: 0, + whiteSpace: 'nowrap', + width: 1, +}); + +// +export function ImageUploadButton({ + buttonSize, + fontSize, + loading = false, + isDisabled = false, + onClick, + type +}) { + //Create Upload file Function + const handleFileChange = (event) => { + const file = event.target.files[0]; + if (file) { + // Check if the file type is jpg/jpeg or png + if (file.type === 'image/jpeg' || file.type === 'image/png') { + console.log('Valid image file selected:', file.name); + // Here you can add your file handling logic + } else { + alert('Please select only JPG or PNG images'); + // Clear the input + event.target.value = ''; + } + } + }; + const sizeConfig = Button_Config[buttonSize] || Button_Config.long; //set Button Size + return ( +
+ } + style={{ borderRadius: 8, fontWeight: 'bold' }} + onClick={onClick} + type={type} + sx={{ + fontSize: fontSize, + padding: sizeConfig.padding + }} + > + Upload + + +
+ + ); +} + +//Add Button +export function AddButton({ + name, + color, + loading = false, + isDisabled = false, + isFixed, + isBold, + fontSize, + buttonSize, + isRounded, + onClick, + type +}) { + const sizeConfig = Button_Config[buttonSize] || Button_Config.medium; //set Button Size + const borderRadius = isRounded ? '30px' : '8px'; //set rounded Border + return ( +
+ + } + style={{ borderRadius: borderRadius }} + sx={{ + fontSize: fontSize, + fontWeight: isBold ? 700 : 400, + padding: sizeConfig.padding, + width: isFixed ? sizeConfig.fixedWidth : 'auto', + '& .MuiButton-startIcon': { + marginRight: '8px', + }, + }} + > + {name} + +
+ + ); +} + +//How to Use + +// +// + +// +// + +// +// + +// +// + diff --git a/client/src/AtomicComponents/Cards/Actioncard.jsx b/client/src/AtomicComponents/Cards/Actioncard.jsx new file mode 100644 index 0000000..af6f2ff --- /dev/null +++ b/client/src/AtomicComponents/Cards/Actioncard.jsx @@ -0,0 +1,20 @@ +import { Card, CardActions, CardContent, Button, Typography } from "@mui/material"; + +export default function Actioncard({ title = "Action Card", description = "Click below for details", buttonText = "Learn More", onClick }) { + return ( + + + {title} + + {description} + + + + + + + ); +} + +// how to use: +// console.log("Button Clicked")} /> diff --git a/client/src/AtomicComponents/Cards/Basiccard.jsx b/client/src/AtomicComponents/Cards/Basiccard.jsx new file mode 100644 index 0000000..4601360 --- /dev/null +++ b/client/src/AtomicComponents/Cards/Basiccard.jsx @@ -0,0 +1,17 @@ +import { Card, CardContent, Typography } from "@mui/material"; + +export default function Basiccard({ title = "Card Title", description = "Card description..." }) { + return ( + + + {title} + + {description} + + + + ); +} + +// how to use: +// diff --git a/client/src/AtomicComponents/Cards/Customercard.jsx b/client/src/AtomicComponents/Cards/Customercard.jsx new file mode 100644 index 0000000..b0b8203 --- /dev/null +++ b/client/src/AtomicComponents/Cards/Customercard.jsx @@ -0,0 +1,31 @@ +import React from "react"; +import { Typography } from "@mui/material"; + +export default function CustomerCard({ name, type, src }) { + return ( +
+
+ image +
+
+ + {name} + + + {type} + +
+
+ ); +} diff --git a/client/src/AtomicComponents/Cards/Loadingskeleton.jsx b/client/src/AtomicComponents/Cards/Loadingskeleton.jsx new file mode 100644 index 0000000..b1fc8d9 --- /dev/null +++ b/client/src/AtomicComponents/Cards/Loadingskeleton.jsx @@ -0,0 +1,21 @@ +import { Card, CardContent, Skeleton } from "@mui/material"; + +export default function LoadingSkeleton() { + return ( + + {/* Simulated Image Placeholder */} + + + + {/* Simulated Title Placeholder */} + + + {/* Simulated Description Placeholder */} + + + + ); +} + +// Use: +// diff --git a/client/src/AtomicComponents/Cards/Mediacard.jsx b/client/src/AtomicComponents/Cards/Mediacard.jsx new file mode 100644 index 0000000..d9247a2 --- /dev/null +++ b/client/src/AtomicComponents/Cards/Mediacard.jsx @@ -0,0 +1,19 @@ +import { Card, CardContent, CardMedia, Typography } from "@mui/material"; + +export default function MediaCard({ image, title = "Media Card", description = "Media description..." }) { + return ( + + + + {title} + + {description} + + + + ); +} + +// Usage: +// + diff --git a/client/src/AtomicComponents/Cards/OrderDetailsCard.jsx b/client/src/AtomicComponents/Cards/OrderDetailsCard.jsx new file mode 100644 index 0000000..48aa468 --- /dev/null +++ b/client/src/AtomicComponents/Cards/OrderDetailsCard.jsx @@ -0,0 +1,86 @@ +import React from "react"; +import { Card, CardContent, Button, Divider } from "@mui/material"; + +const OrderCard = ({ + status, + itemName, + totalAmount, + orderDate, + orderId, + imageUrl, +}) => { + return ( + + +
+

{status}

+
+
+

Order date: {orderDate}

+

+ Order ID: {orderId}{" "} + Copy +

+
+

Order Details >

+
+
+ + + +
+
+ {itemName} +
+

+ {itemName} +

+

{totalAmount}

+
+
+
+

+ Total: {totalAmount} +

+
+ + +
+
+
+
+
+ ); +}; + +export default OrderCard; diff --git a/client/src/AtomicComponents/Cards/PCBuildCard.jsx b/client/src/AtomicComponents/Cards/PCBuildCard.jsx new file mode 100644 index 0000000..17598ba --- /dev/null +++ b/client/src/AtomicComponents/Cards/PCBuildCard.jsx @@ -0,0 +1,43 @@ +import React from "react"; +import { Card, CardContent, Button } from "@mui/material"; + +const PCBuildCard = ({ image, name, score, specs }) => { + return ( + + {/* PC Image */} +
+

{name}

+ {name} +
+ + {/* PC Info */} + + {/* Score */} +
+ + Score: {score} + + +
+ + {/* Specifications */} +
    + {specs.map(([key, value], index) => ( +
  • + {key} + {value} +
  • + ))} +
+
+
+ ); +}; + +export default PCBuildCard; diff --git a/client/src/AtomicComponents/Cards/Productcard.jsx b/client/src/AtomicComponents/Cards/Productcard.jsx new file mode 100644 index 0000000..e3aadbb --- /dev/null +++ b/client/src/AtomicComponents/Cards/Productcard.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Typography } from "@mui/material"; + + +export default function ProductCard({ name, type, src }) { + return ( +
+
+ image +
+
+ {name} + {type} +
+
+ ); +} \ No newline at end of file diff --git a/client/src/AtomicComponents/Cards/PublishedBuildCard.jsx b/client/src/AtomicComponents/Cards/PublishedBuildCard.jsx new file mode 100644 index 0000000..30bfb74 --- /dev/null +++ b/client/src/AtomicComponents/Cards/PublishedBuildCard.jsx @@ -0,0 +1,45 @@ +import React from "react"; +import { Card, CardContent, Avatar } from "@mui/material"; + +const PublishedBuildCard = ({ + image, + buildName, + username, + userIcon, + description, + score, +}) => { + return ( + + {/* Image Section */} +
+ {buildName} +
+ + {/* Content Section */} + +
+

{buildName}

+ + Score: {score} + +
+ + {/* Description */} +

+ {description} +

+ + {/* User Info */} +
+ + + {username} + +
+
+
+ ); +}; + +export default PublishedBuildCard; diff --git a/client/src/AtomicComponents/Cards/QuantityCard.jsx b/client/src/AtomicComponents/Cards/QuantityCard.jsx new file mode 100644 index 0000000..55750fd --- /dev/null +++ b/client/src/AtomicComponents/Cards/QuantityCard.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Typography } from "@mui/material"; + + +export default function QuantityCard({ quantity, unitprice }) { + return ( +
+ {quantity} + {unitprice} +
+ ); +} \ No newline at end of file diff --git a/client/src/AtomicComponents/Cards/StatusCard.jsx b/client/src/AtomicComponents/Cards/StatusCard.jsx new file mode 100644 index 0000000..868600d --- /dev/null +++ b/client/src/AtomicComponents/Cards/StatusCard.jsx @@ -0,0 +1,21 @@ +import React from "react"; + +function StatusCard({ Status }) { + return ( +
+ {Status === "In Stock" && ( +
{Status}
+ )} + {Status === "Low Stock" && ( +
{Status}
+ )} + {Status === "Out of Stock" && ( +
{Status}
+ )} +
+ ); +} +export default StatusCard +//product.quantity > 5 ? "In Stock" : product.quantity <= 5 && product.quantity > 0 ? "Low Stock" : "Out of Stock", + + diff --git a/client/src/AtomicComponents/Cards/TimeCard.jsx b/client/src/AtomicComponents/Cards/TimeCard.jsx new file mode 100644 index 0000000..d0f92d6 --- /dev/null +++ b/client/src/AtomicComponents/Cards/TimeCard.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Typography } from "@mui/material"; + + +export default function TimeCard({ date, time }) { + return ( +
+ {date} + {time} +
+ ); +} \ No newline at end of file diff --git a/client/src/AtomicComponents/Cards/Usercard.jsx b/client/src/AtomicComponents/Cards/Usercard.jsx new file mode 100644 index 0000000..61640a6 --- /dev/null +++ b/client/src/AtomicComponents/Cards/Usercard.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Avatar, Typography, Box } from "@mui/material"; + +export default function UserCard({ name, email, src }) { + return ( + + + + {name} + {email} + + + ); +} + + + + +//how to useee +// diff --git a/client/src/AtomicComponents/Cards/mediacards/Itemcard.jsx b/client/src/AtomicComponents/Cards/mediacards/Itemcard.jsx new file mode 100644 index 0000000..875f9bf --- /dev/null +++ b/client/src/AtomicComponents/Cards/mediacards/Itemcard.jsx @@ -0,0 +1,61 @@ + +export default function Itemcard({ src="/graph1.png" , stock="In Stock" , itemname = "ASUS ROG Strix RTX 4080 SUPER 16GB GDDR6X", price = "610,000 LKR" }) { + return ( + + +
+ {/* full border area up */} + + + {/* stock availability area */} + +
+ {stock} +
+ + + + {/* image area */} + +
+ {itemname}/ +
+ + + + + {/* name area */} + +
+

+

{itemname}

+

+
+ + + + + + {/* price area */} +

{price}

+ + + + {/* add to cart button area -- will replace with atomic button */} +
+ +
+ + +
+ ); + } + + + + + //how to useee-- + + // \ No newline at end of file diff --git a/client/src/AtomicComponents/Cards/mediacards/Itemcardsforpc.jsx b/client/src/AtomicComponents/Cards/mediacards/Itemcardsforpc.jsx new file mode 100644 index 0000000..4f95ab3 --- /dev/null +++ b/client/src/AtomicComponents/Cards/mediacards/Itemcardsforpc.jsx @@ -0,0 +1,61 @@ + +export default function Itemcardforpc({ src="/graph1.png" , stock="In Stock" , itemname = "Player 1:Intel ARC Edition", price = "710,000 LKR" }) { + return ( + + +
+ {/* full border area up */} + + + {/* stock availability area */} + +
+ {stock} +
+ + + + {/* image area */} + +
+ {itemname}/ +
+ + + + + {/* name area */} + +
+

+

{itemname}

+

+
+ + + + + + {/* price area */} +

{price}

+ + + + {/* add to cart button area -- will replace with atomic button */} +
+ +
+ + +
+ ); + } + + + + + //how to useee-- + + // \ No newline at end of file diff --git a/client/src/AtomicComponents/Dialogs/Dialogs.jsx b/client/src/AtomicComponents/Dialogs/Dialogs.jsx new file mode 100644 index 0000000..a8eb303 --- /dev/null +++ b/client/src/AtomicComponents/Dialogs/Dialogs.jsx @@ -0,0 +1,39 @@ +import * as React from 'react'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import DialogTitle from '@mui/material/DialogTitle'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import theme from '../theme'; +import { TextButton } from '../Buttons/Buttons'; + +export default function DialogAlert({ Title, message, Agree, Disagree, open, handleClose, handleAgree }) { + + const fullScreen = useMediaQuery(theme.breakpoints.down('md')); + + return ( + + + {Title} + + + + {message} + + + + + + + + + + + ); +} diff --git a/client/src/AtomicComponents/ForAdminForms/Category.jsx b/client/src/AtomicComponents/ForAdminForms/Category.jsx new file mode 100644 index 0000000..d4b7274 --- /dev/null +++ b/client/src/AtomicComponents/ForAdminForms/Category.jsx @@ -0,0 +1,515 @@ +const main = [ + { value: "Necessary", label: "Custom Build Necessary" }, + { value: "Optional", label: "Custom Build Optional" }, + { value: "Common", label: "Individual Category" }, +]; +const StockType = [ + { value: "InStock", label: "In Stock" }, + { value: "OutStock", label: "Out of Stock" }, + { value: "lowStock", label: "Low Stock" }, +]; +const InvoiceStatus = [ + { value: "draft", label: "Draft" }, + { value: "sent", label: "Sent" }, + { value: "paid", label: "Paid" }, + { value: "pending", label: "Pending" }, + { value: "partiallypaid", label: "Partially Paid" }, + { value: "overdue", label: "Overdue" }, + { value: "cancelled", label: "Cancelled" }, + { value: "refunded", label: "Refunded" }, +]; +const subCategories = { + Necessary: [ + { value: "ram", label: "Ram" }, + { value: "gpu", label: "Graphic Cards" }, + { value: "processors", label: "Processors" }, + { value: "motherboard", label: "Motherboard" }, + { value: "storage", label: "Storages" }, + { value: "casing", label: "Casing" }, + { value: "power", label: "Power Supply" }, + ], + Optional: [ + { value: "cooling", label: "Cooling" }, + { value: "keyboard", label: "Keyboard" }, + { value: "mouse", label: "Mouse" }, + { value: "monitor", label: "Monitor" }, + { value: "ups", label: "UPS" }, + { value: "expansion_network", label: "Expansion Card & Networking" }, + { value: "gamepad", label: "Gamepad" }, + ], + Common: [ + { value: "laptop", label: "Laptop" }, + { value: "prebuilds", label: "Prebuilds" }, + { value: "accessories", label: "Steaming Accessories" }, + { value: "externals", label: "External Storage" }, + { value: "cables_connectors", label: "Cables & Connectors" }, + ], +}; + +const manufacture = { + processors: [ + { value: "intel", label: "Intel" }, + { value: "amd", label: "AMD" }, + ], + ram: [ + { value: "corsair", label: "Corsair" }, + { value: "team", label: "Team" }, + { value: "gskill", label: "GSKILL" }, + { value: "hyperx", label: "HyperX" }, + { value: "adata", label: "ADATA" }, + ], + motherboard: [ + { value: "asus", label: "ASUS" }, + { value: "gigabyte", label: "Gigabyte" }, + { value: "msi", label: "MSI" }, + ], + vga: [ + { value: "nvidia", label: "NVIDIA" }, + { value: "amd", label: "AMD" }, + { value: "msi", label: "MSI" }, + { value: "zotac", label: "Zotac" }, + { value: "corsair", label: "Corsair" }, + { value: "asus", label: "ASUS" }, + ], + storage: [ + { value: "samsung", label: "Samsung" }, + { value: "seagate", label: "Seagate" }, + { value: "western_digital", label: "Western Digital" }, + { value: "toshiba", label: "Toshiba" }, + { value: "adata", label: "ADATA" }, + { value: "kingston", label: "Kingston" }, + ], + casing: [], + power: [], + cooling: [ + { value: "noctua", label: "Noctua" }, + { value: "corsair", label: "Corsair" }, + { value: "bequiet", label: "Be Quiet" }, + { value: "arctic", label: "Arctic" }, + { value: "coolerMaster", label: "Cooler Master" }, + { value: "nzxt", label: "NZXT" }, + { value: "adata", label: "Adata" }, + { value: "lian_li", label: "Lian Li" }, + { value: "antec", label: "Antec" }, + ], + keyboard: [ + { value: "logitech", label: "Logitech" }, + { value: "hyperx", label: "HyperX" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "razer", label: "Razer" }, + { value: "asus", label: "ASUS" }, + ], + mouse: [ + { value: "logitech", label: "Logitech" }, + { value: "hyperx", label: "HyperX" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "razer", label: "Razer" }, + { value: "asus", label: "ASUS" }, + ], + monitor: [ + { value: "asus", label: "ASUS" }, + { value: "acer", label: "Acer" }, + { value: "dell", label: "Dell" }, + { value: "hp", label: "HP" }, + { value: "lenovo", label: "Lenovo" }, + ], + ups: [ + { value: "apc", label: "APC" }, + { value: "tripplite", label: "Tripplite" }, + { value: "cyberpowerpc", label: "CyberPowerPC" }, + ], + expansion_network: [], + gamepad: [], + laptop: [ + { value: "dell", label: "Dell" }, + { value: "lenovo", label: "Lenovo" }, + { value: "hp", label: "HP" }, + { value: "asus", label: "ASUS" }, + { value: "acer", label: "Acer" }, + { value: "msi", label: "MSI" }, + { value: "hp", label: "HP" }, + { value: "gigabyte", label: "Gigabyte" }, + ], + prebuilds: [], +}; + +const socketTypes = { + intel: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + ], + amd: [ + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" }, + ], +}; + +const cpuCores = [ + { value: "4", label: "4 Cores" }, + { value: "6", label: "6 Cores" }, + { value: "8", label: "8 Cores" }, + { value: "10", label: "10 Cores" }, + { value: "12", label: "12 Cores" }, + { value: "14", label: "14 Cores" }, + { value: "16", label: "16 Cores" }, + { value: "20", label: "20 Cores" }, + { value: "24", label: "24 Cores" }, +]; + +const cpuThreads = [ + { value: "4", label: "4 Threads" }, + { value: "6", label: "6 Threads" }, + { value: "8", label: "8 Threads" }, + { value: "12", label: "12 Threads" }, + { value: "14", label: "14 Threads" }, + { value: "16", label: "16 Threads" }, + { value: "20", label: "20 Threads" }, + { value: "24", label: "24 Threads" }, + { value: "28", label: "28 Threads" }, + { value: "32", label: "32 Threads" }, + { value: "64", label: "64 Threads" }, +]; + +const ramAttributes = { + type: [ + { value: "ddr3", label: "DDR3" }, + { value: "ddr4", label: "DDR4" }, + { value: "ddr5", label: "DDR5" }, + { value: "lpddr4x", label: "LPDDR4X" }, + { value: "lpddr5", label: "LPDDR5" }, + ], + speed: [ + { value: 2133, label: "2133 MHz" }, + { value: 2666, label: "2666 MHz" }, + { value: 3000, label: "3000 MHz" }, + { value: 3200, label: "3200 MHz" }, + { value: 3600, label: "3600 MHz" }, + { value: 4000, label: "4000 MHz" }, + { value: 4800, label: "4800 MHz" }, + { value: 5600, label: "5600 MHz" }, + { value: 6400, label: "6400 MHz" }, + ], + size: [ + { value: 4, label: "4GB" }, + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + { value: 128, label: "128GB" }, + ], +}; + +const motherboardAttributes = { + chipsets: [ + { value: "B550", label: "B550" }, + { value: "B650", label: "B650" }, + { value: "B660", label: "B660" }, + { value: "B660M", label: "B660M" }, + { value: "X570", label: "X570" }, + { value: "X670", label: "X670" }, + { value: "X670E", label: "X670E" }, + { value: "X670_PRO", label: "X670 PRO" }, + { value: "Z690", label: "Z690" }, + { value: "Z790", label: "Z790" }, + { value: "H610", label: "H610" }, + { value: "H670", label: "H670" }, + ], + motherboardSocket: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" }, + ], + formFactor: [ + { value: "atx", label: "ATX" }, + { value: "micro_atx", label: "Micro ATX" }, + { value: "mini_itx", label: "Mini ITX" }, + { value: "e_atx", label: "E-ATX" }, + ], + ramSlots: [ + { value: "2", label: "2 Slots" }, + { value: "4", label: "4 Slots" }, + { value: "8", label: "8 Slots" }, + ], + maxRam: [ + { value: "32", label: "32GB" }, + { value: "64", label: "64GB" }, + { value: "128", label: "128GB" }, + { value: "256", label: "256GB" }, + ], + pcieSlotType: [], + pcieVersion: [], + storageType: [], + expansionSlots: [], + memoryTypes: [ + { value: "ddr3", label: "DDR3" }, + { value: "ddr4", label: "DDR4" }, + { value: "ddr5", label: "DDR5" }, + ], +}; + +const storageAttributes = { + storageTypes: [ + { value: "nvme_m2", label: "NVMe M.2" }, + { value: "sata_ssd", label: "SATA SSD" }, + { value: "hdd", label: "HDD" }, + { value: "m2_sata", label: "M.2 SATA" }, + { value: "sas_hdd", label: "SAS HDD" }, + { value: "pata_hdd", label: "PATA HDD" }, + ], + storageCapacities: [ + { value: "256", label: "256GB" }, + { value: "512", label: "512GB" }, + { value: "1000", label: "1TB" }, + { value: "2000", label: "2TB" }, + { value: "4000", label: "4TB" }, + { value: "8000", label: "8TB" }, + ], +}; + +const gpuAttributes = { + interfaceType: [ + { value: "pcie_x16", label: "PCIe x16" }, + { value: "pcie_x8", label: "PCIe x8" }, + { value: "pcie_4_0", label: "PCIe 4.0" }, + { value: "pcie_5_0", label: "PCIe 5.0" }, + { value: "agp", label: "AGP" }, + { value: "pci", label: "PCI" }, + ], + powerConnectors: [ + { value: "6-pin", label: "6-pin" }, + { value: "8-pin", label: "8-pin" }, + { value: "6+8-pin", label: "6+8-pin" }, + { value: "2x8-pin", label: "2x8-pin" }, + { value: "12-pin", label: "12-pin" }, + { value: "16-pin", label: "16-pin (12VHPWR)" }, + ], + gpuVram: [ + { value: "4", label: "4GB" }, + { value: "8", label: "8GB" }, + { value: "12", label: "12GB" }, + { value: "16", label: "16GB" }, + { value: "24", label: "24GB" }, + { value: "48", label: "48GB" }, + ], +}; + +const casingAttributes = { + formFactor: [ + { value: "mid_tower", label: "Mid Tower" }, + { value: "full_tower", label: "Full Tower" }, + { value: "mini_tower", label: "Mini Tower" }, + { value: "cube", label: "Cube" }, + { value: "open_frame", label: "Open Frame" }, + ], + supportedMotherboardSizes: [ + { value: "atx", label: "ATX" }, + { value: "micro_atx", label: "Micro-ATX" }, + { value: "mini_itx", label: "Mini-ITX" }, + { value: "e_atx", label: "E-ATX" }, + { value: "xl_atx", label: "XL-ATX" }, + ], +}; + +const keyboardAttributes = { + manufacturer: [ + { value: "logitech", label: "Logitech" }, + { value: "razer", label: "Razer" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "coolermaster", label: "Cooler Master" }, + ], + type: [ + { value: "mechanical", label: "Mechanical" }, + { value: "membrane", label: "Membrane" }, + { value: "hybrid", label: "Hybrid" }, + ], +}; + +const mouseAttributes = { + type: [ + { value: "wired", label: "Wired" }, + { value: "wireless", label: "Wireless" }, + { value: "bluetooth", label: "Bluetooth" }, + ], +}; + +const coolerAttributes = { + supportedSocket: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" }, + ], + coolerType: [ + { value: "air", label: "Air" }, + { value: "liquid", label: "Liquid" }, + ], +}; + +const monitorAttributes = { + displaySize: [ + { value: 19, label: "19 inches" }, + { value: 20, label: "20 inches" }, + { value: 22, label: "22 inches" }, + { value: 24, label: "24 inches" }, + { value: 27, label: "27 inches" }, + { value: 32, label: "32 inches" }, + { value: 34, label: "34 inches" }, + { value: 42, label: "42 inches" }, + ], + resolution: [ + { value: "1920x1080", label: "1920x1080 (Full HD)" }, + { value: "2560x1440", label: "2560x1440 (QHD)" }, + { value: "3840x2160", label: "3840x2160 (4K UHD)" }, + { value: "5120x1440", label: "5120x1440 (Super Ultra-Wide)" }, + ], + refreshRate: [ + { value: 60, label: "60Hz" }, + { value: 75, label: "75Hz" }, + { value: 120, label: "120Hz" }, + { value: 144, label: "144Hz" }, + { value: 240, label: "240Hz" }, + ], + panelType: [ + { value: "tn", label: "TN (Twisted Nematic)" }, + { value: "ips", label: "IPS (In-Plane Switching)" }, + { value: "va", label: "VA (Vertical Alignment)" }, + { value: "oled", label: "OLED" }, + ], + monitorType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "office", label: "Office" }, + { value: "portable", label: "Portable" }, + ], +}; + +const laptopAttributes = { + displaySize: [ + { value: 13, label: "13 inches" }, + { value: 14, label: "14 inches" }, + { value: 15, label: "15.6 inches" }, + { value: 16, label: "16 inches" }, + { value: 17, label: "17 inches" }, + ], + resolution: [ + { value: "1920x1080", label: "1920x1080 (Full HD)" }, + { value: "2560x1600", label: "2560x1600 (WQXGA)" }, + { value: "2880x1800", label: "2880x1800 (2.8K)" }, + { value: "3840x2160", label: "3840x2160 (4K UHD)" }, + ], + cpu: [ + { value: "intel_core_i3", label: "Intel Core i3" }, + { value: "intel_core_i5", label: "Intel Core i5" }, + { value: "intel_core_i7", label: "Intel Core i7" }, + { value: "intel_core_i9", label: "Intel Core i9" }, + { value: "amd_ryzen_5", label: "AMD Ryzen 5" }, + { value: "amd_ryzen_7", label: "AMD Ryzen 7" }, + { value: "amd_ryzen_9", label: "AMD Ryzen 9" }, + ], + ram: [ + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + ], + storage: [ + { value: 256, label: "256GB" }, + { value: 512, label: "512GB" }, + { value: 1024, label: "1TB" }, + { value: 2048, label: "2TB" }, + ], + laptopType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "personal", label: "Personal" }, + ], + graphicsCard: [ + { value: "intel_integrated", label: "Intel Integrated GPU" }, + { value: "amd_integrated", label: "AMD Integrated GPU" }, + { value: "nvidia_rtx_4060", label: "NVIDIA RTX 4060" }, + { value: "nvidia_rtx_4080", label: "NVIDIA RTX 4080" }, + { value: "amd_radeon_rx_7600", label: "AMD Radeon RX 7600" }, + ], +}; + +const desktopAttributes = { + cpu: [ + { value: "intel_core_i7_11700f", label: "Intel Core i7-11700F" }, + { value: "intel_core_i5_13400", label: "Intel Core i5-13400" }, + { value: "intel_core_i9_13900k", label: "Intel Core i9-13900K" }, + { value: "amd_ryzen_5_7600x", label: "AMD Ryzen 5 7600X" }, + { value: "amd_ryzen_7_7800x3d", label: "AMD Ryzen 7 7800X3D" }, + { value: "amd_ryzen_9_7950x", label: "AMD Ryzen 9 7950X" }, + ], + gpu: [ + { value: "nvidia_geforce_rtx_3080", label: "NVIDIA GeForce RTX 3080" }, + { value: "nvidia_geforce_rtx_4070", label: "NVIDIA GeForce RTX 4070" }, + { value: "nvidia_geforce_rtx_4090", label: "NVIDIA GeForce RTX 4090" }, + { value: "amd_radeon_rx_6800", label: "AMD Radeon RX 6800" }, + { value: "amd_radeon_rx_7900_xt", label: "AMD Radeon RX 7900 XT" }, + { value: "intel_arc_a770", label: "Intel Arc A770" }, + ], + ram: [ + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + { value: 128, label: "128GB" }, + ], + storage: [ + { value: 256, label: "256GB" }, + { value: 512, label: "512GB" }, + { value: 1024, label: "1TB" }, + { value: 2048, label: "2TB" }, + { value: 4096, label: "4TB" }, + ], + desktopType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "personal", label: "Personal" }, + { value: "workstation", label: "Workstation" }, + ], +}; + +// const allSubCategoryOptions = Object.values(subCategories).flatMap(options => options); + +export { + main, + StockType, + subCategories, + manufacture, + socketTypes, + cpuCores, + cpuThreads, + coolerAttributes, + gpuAttributes, + ramAttributes, + motherboardAttributes, + storageAttributes, + casingAttributes, + keyboardAttributes, + mouseAttributes, + monitorAttributes, + laptopAttributes, + desktopAttributes, + InvoiceStatus, +}; diff --git a/client/src/AtomicComponents/ForCustomBuild/BudgetSelector.jsx b/client/src/AtomicComponents/ForCustomBuild/BudgetSelector.jsx new file mode 100644 index 0000000..87560a9 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/BudgetSelector.jsx @@ -0,0 +1,77 @@ +import React, { useState, useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; + +function BudgetSelector({ budget, onBudgetChange, onApply }) { + const [sliderValue, setSliderValue] = useState(budget); + const sliderRef = useRef(null); + + const handleSliderChange = (e) => { + const value = parseInt(e.target.value); + setSliderValue(value); + updateSliderProgress(value); + }; + + const handleSliderChangeEnd = () => { + onBudgetChange(sliderValue); + }; + + const updateSliderProgress = (value) => { + if (sliderRef.current) { + const percentage = (value / 2000000) * 100; + sliderRef.current.style.setProperty('--range-progress', `${percentage}%`); + } + }; + + useEffect(() => { + updateSliderProgress(budget); + }, [budget]); + + const formatBudget = (value) => { + return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); + }; + + return ( +
+
+

Budget

+
+
+

{formatBudget(budget)}LKR

+
+
+ 0LKR +
+ +
+ 2,000,000LKR +
+
+ +
+
+ ); +} + +BudgetSelector.propTypes = { + budget: PropTypes.number.isRequired, + onBudgetChange: PropTypes.func.isRequired, + onApply: PropTypes.func.isRequired, +}; + +export default BudgetSelector; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/CustomButton.jsx b/client/src/AtomicComponents/ForCustomBuild/CustomButton.jsx new file mode 100644 index 0000000..9caed69 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/CustomButton.jsx @@ -0,0 +1,34 @@ +import React from 'react'; + +const CustomButton = ({ text }) => { + return ( + + ); +}; + +export default CustomButton; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/CustomContainer.jsx b/client/src/AtomicComponents/ForCustomBuild/CustomContainer.jsx new file mode 100644 index 0000000..dff3ca3 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/CustomContainer.jsx @@ -0,0 +1,65 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import CustomButton from './CustomButton'; + +const CustomContainer = ({ heading, subheading, buttonText }) => { + return ( +
+ +
+ +

+ {heading} +

+ + +

+ {subheading} +

+
+ + + +
+ ); +}; + + +CustomContainer.propTypes = { + heading: PropTypes.string.isRequired, + subheading: PropTypes.string.isRequired, + buttonText: PropTypes.string.isRequired, +}; + +export default CustomContainer; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge.jsx b/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge.jsx new file mode 100644 index 0000000..c16c8fe --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import CustomContainer from './CustomContainer'; + +const CustomContainerLarge = ({ heading, subheading, buttonText, imageUrl }) => { + return ( +
+ +
+ +
+ + +
+ Container Image +
+
+ ); +}; + + +CustomContainerLarge.propTypes = { + heading: PropTypes.string.isRequired, + subheading: PropTypes.string.isRequired, + buttonText: PropTypes.string.isRequired, + imageUrl: PropTypes.string.isRequired, +}; + +export default CustomContainerLarge; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge2.jsx b/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge2.jsx new file mode 100644 index 0000000..e3201ad --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/CustomContainerLarge2.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import CustomContainer from './CustomContainer'; + +const CustomContainerLarge2 = ({ heading, subheading, buttonText, imageUrl }) => { + return ( +
+ + Container Image + + +
+ +
+ + +
+ ); +}; + + +CustomContainerLarge2.propTypes = { + heading: PropTypes.string.isRequired, + subheading: PropTypes.string.isRequired, + buttonText: PropTypes.string.isRequired, + imageUrl: PropTypes.string.isRequired, +}; + +export default CustomContainerLarge2; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/GameCard.jsx b/client/src/AtomicComponents/ForCustomBuild/GameCard.jsx new file mode 100644 index 0000000..4bab578 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/GameCard.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function GameCard({ game, onClick, onRemove }) { + return ( +
+
+ {game.name} +
+

{game.name}

+ +
+ ); +} + +GameCard.propTypes = { + game: PropTypes.shape({ + image: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + scores: PropTypes.shape({ + cpu: PropTypes.number, + gpu: PropTypes.number, + ram: PropTypes.number, + total: PropTypes.number, + }), + }).isRequired, + onClick: PropTypes.func.isRequired, + onRemove: PropTypes.func.isRequired, // New prop for removal +}; + +export default GameCard; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/GameDetailPopup.jsx b/client/src/AtomicComponents/ForCustomBuild/GameDetailPopup.jsx new file mode 100644 index 0000000..4584725 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/GameDetailPopup.jsx @@ -0,0 +1,110 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function GameDetailPopup({ game, onClose }) { + return ( +
+
+
+
+

{game.name}

+ +
+
+ {game.name} +
+
+

Description

+

{game.description}

+
+
+

Total Performance Score

+

+ Score: {game.scores?.total ? game.scores.total.toFixed(2) : 'N/A'} +

+
+
+

Recommended Scores

+
+
+

CPU Score

+

+ {game.scores?.cpu ? game.scores.cpu.toFixed(2) : 'N/A'} +

+
+
+

GPU Score

+

+ {game.scores?.gpu ? game.scores.gpu.toFixed(2) : 'N/A'} +

+
+
+

RAM Score

+

+ {game.scores?.ram ? game.scores.ram.toFixed(2) : 'N/A'} +

+
+
+
+
+
+
+ ); +} + +GameDetailPopup.propTypes = { + game: PropTypes.shape({ + name: PropTypes.string.isRequired, + image: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + scores: PropTypes.shape({ + cpu: PropTypes.number, + gpu: PropTypes.number, + ram: PropTypes.number, + total: PropTypes.number, + }), + cpu: PropTypes.shape({ + cores: PropTypes.number.isRequired, + threads: PropTypes.number.isRequired, + baseClock: PropTypes.number.isRequired, + boostClock: PropTypes.number.isRequired, + }).isRequired, + gpu: PropTypes.shape({ + series: PropTypes.string.isRequired, + vramGB: PropTypes.number.isRequired, + boostClockMHz: PropTypes.number.isRequired, + cores: PropTypes.number.isRequired, + }).isRequired, + ram: PropTypes.shape({ + sizeGB: PropTypes.number.isRequired, + speedMHz: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, + onClose: PropTypes.func.isRequired, +}; + +export default GameDetailPopup; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/GameSelector.jsx b/client/src/AtomicComponents/ForCustomBuild/GameSelector.jsx new file mode 100644 index 0000000..1737c13 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/GameSelector.jsx @@ -0,0 +1,119 @@ +import React, { useState, useRef, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import GameCard from './GameCard'; +import SearchBar from './SearchBar'; +import GameDetailPopup from './GameDetailPopup'; +import { calculateCPUScore, calculateGPUScore, calculateRAMScore, calculateTotalScore } from '../../utils/scoreCalculator'; + +function GameSelector({ selectedGames, onGameSelect, onRemoveGame }) { + const [isSearchExpanded, setIsSearchExpanded] = useState(false); + const [selectedGame, setSelectedGame] = useState(null); + const [showGameDetail, setShowGameDetail] = useState(false); + const searchRef = useRef(null); + + useEffect(() => { + function handleClickOutside(event) { + if (searchRef.current && !searchRef.current.contains(event.target)) { + setIsSearchExpanded(false); + } + } + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [searchRef]); + + const handleGameSelectInternal = (game) => { + const cpuScore = calculateCPUScore(game.cpu); + const gpuScore = calculateGPUScore(game.gpu); + const ramScore = calculateRAMScore(game.ram); + const totalScore = calculateTotalScore(cpuScore, gpuScore, ramScore); + + const gameWithScores = { + ...game, + scores: { + cpu: cpuScore, + gpu: gpuScore, + ram: ramScore, + total: totalScore + } + }; + onGameSelect(gameWithScores); + setIsSearchExpanded(false); + }; + + const handleGameCardClick = (game) => { + setSelectedGame(game); + setShowGameDetail(true); + }; + + const handleCloseDetail = () => { + setShowGameDetail(false); + }; + + return ( +
+
+

Selected Games

+
+ setIsSearchExpanded(true)} + onGameSelect={handleGameSelectInternal} + /> +
+
+
+ {selectedGames.map((game) => ( + handleGameCardClick(game)} + onRemove={() => onRemoveGame(game.id)} + /> + ))} +
+ {showGameDetail && selectedGame && ( + + )} +
+ ); +} + +GameSelector.propTypes = { + selectedGames: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + image: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + scores: PropTypes.shape({ + cpu: PropTypes.number, + gpu: PropTypes.number, + ram: PropTypes.number, + total: PropTypes.number, + }), + cpu: PropTypes.shape({ + cores: PropTypes.number.isRequired, + threads: PropTypes.number.isRequired, + baseClock: PropTypes.number.isRequired, + boostClock: PropTypes.number.isRequired, + }).isRequired, + gpu: PropTypes.shape({ + series: PropTypes.string.isRequired, + vramGB: PropTypes.number.isRequired, + boostClockMHz: PropTypes.number.isRequired, + cores: PropTypes.number.isRequired, + }).isRequired, + ram: PropTypes.shape({ + sizeGB: PropTypes.number.isRequired, + speedMHz: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + }).isRequired, + }) + ).isRequired, + onGameSelect: PropTypes.func.isRequired, + onRemoveGame: PropTypes.func.isRequired, // New prop for removing games +}; + +export default GameSelector; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/PrebuiltPcPopup.jsx b/client/src/AtomicComponents/ForCustomBuild/PrebuiltPcPopup.jsx new file mode 100644 index 0000000..198aee1 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/PrebuiltPcPopup.jsx @@ -0,0 +1,115 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { calculatePrebuiltPcScore } from '../../utils/scoreCalculator'; + +function PrebuiltPcPopup({ prebuiltPcs, budget, highestGameScore, onClose }) { + const filteredPrebuilds = prebuiltPcs + .map((pc) => { + const scores = calculatePrebuiltPcScore(pc); + return { ...pc, scores }; + }) + .filter((pc) => pc.scores.total >= highestGameScore && pc.price <= budget); + + const handleAddToCart = (pc) => { + // Placeholder for cart logic + console.log(`Added to cart: ${pc.name} (ID: ${pc._id})`); + alert(`${pc.name} added to cart!`); // Temporary feedback + // Future: Dispatch to a cart context or send to backend + }; + + return ( +
+
+
+

Recommended Prebuilt PCs

+ +
+ {filteredPrebuilds.length > 0 ? ( +
+ {filteredPrebuilds.map((pc) => ( +
+
+
+ {pc.imgUrls.length > 0 && ( + {pc.name} + )} +
+

{pc.name}

+

Price: {pc.price.toLocaleString()} LKR

+

Total Score: {pc.scores.total.toFixed(2)}

+

+ CPU: {pc.scores.cpu.toFixed(2)} | GPU: {pc.scores.gpu.toFixed(2)} | RAM: {pc.scores.ram.toFixed(2)} +

+
+
+ +
+
+ ))} +
+ ) : ( +

No prebuilt PCs found within your budget that meet the required performance.

+ )} +
+
+ ); +} + +PrebuiltPcPopup.propTypes = { + prebuiltPcs: PropTypes.arrayOf( + PropTypes.shape({ + _id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + price: PropTypes.number.isRequired, + imgUrls: PropTypes.arrayOf( + PropTypes.shape({ + url: PropTypes.string.isRequired, + }) + ), + cpuCores: PropTypes.string, + cpuThreads: PropTypes.string, + cpuBaseClock: PropTypes.string, + cpuBoostClock: PropTypes.string, + gpuSeries: PropTypes.string, + gpuVramGb: PropTypes.string, + gpuBoostClockMhz: PropTypes.string, + gpuCores: PropTypes.string, + ramSizeGb: PropTypes.string, + ramSpeedMhz: PropTypes.string, + ramType: PropTypes.string, + }) + ).isRequired, + budget: PropTypes.number.isRequired, + highestGameScore: PropTypes.number.isRequired, + onClose: PropTypes.func.isRequired, +}; + +export default PrebuiltPcPopup; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/SearchBar.jsx b/client/src/AtomicComponents/ForCustomBuild/SearchBar.jsx new file mode 100644 index 0000000..c08d85d --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/SearchBar.jsx @@ -0,0 +1,157 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import axios from 'axios'; + +function SearchBar({ isExpanded, onExpand, onGameSelect }) { + const [searchTerm, setSearchTerm] = useState(''); + const [searchResults, setSearchResults] = useState([]); + const [showDropdown, setShowDropdown] = useState(false); + const [availableGames, setAvailableGames] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchGames = async () => { + try { + setIsLoading(true); + setError(null); + const response = await axios.get('http://localhost:8000/api/game/games', { + timeout: 5000, + }); + if (response.data.success) { + const transformedGames = response.data.games.map((game) => ({ + id: game._id, + name: game.name, + description: game.description, + image: game.image, + cpu: { + cores: game.cpu.cores, + threads: game.cpu.threads, + baseClock: game.cpu.baseClock, + boostClock: game.cpu.boostClock, + }, + gpu: { + series: game.gpu.series, + vramGB: game.gpu.vramGB, + boostClockMHz: game.gpu.boostClockMHz, + cores: game.gpu.cores, + }, + ram: { + sizeGB: game.ram.sizeGB, + speedMHz: game.ram.speedMHz, + type: game.ram.type, + }, + })); + setAvailableGames(transformedGames); + } else { + setError('Failed to fetch games from server'); + } + } catch (err) { + console.error('Error fetching games:', err.message); + setError('Unable to connect to the server. Please try again later.'); + } finally { + setIsLoading(false); + } + }; + + if (isExpanded) { + fetchGames(); + } + }, [isExpanded]); + + useEffect(() => { + if (searchTerm.trim().length > 0) { + const filteredResults = availableGames.filter((game) => + game.name.toLowerCase().includes(searchTerm.trim().toLowerCase()) + ); + setSearchResults(filteredResults); + setShowDropdown(true); + } else { + setSearchResults([]); + setShowDropdown(false); + } + }, [searchTerm, availableGames]); + + const handleSelectGame = (game) => { + onGameSelect(game); + setSearchTerm(''); + setShowDropdown(false); + }; + + return ( +
+
+ + {isExpanded && ( + setSearchTerm(e.target.value)} + className="bg-transparent text-white placeholder-purple-200 outline-none w-full pr-4" + autoFocus + /> + )} +
+ {isExpanded && showDropdown && ( +
+ {isLoading ? ( +

Loading games...

+ ) : error ? ( +

{error}

+ ) : searchResults.length > 0 ? ( +
    + {searchResults.map((game) => ( +
  • handleSelectGame(game)} + > + {game.name} + {game.name} +
  • + ))} +
+ ) : ( +

No games found

+ )} +
+ )} +
+ ); +} + +SearchBar.propTypes = { + isExpanded: PropTypes.bool.isRequired, + onExpand: PropTypes.func.isRequired, + onGameSelect: PropTypes.func.isRequired, +}; + +export default SearchBar; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForCustomBuild/SelectPcHeader.jsx b/client/src/AtomicComponents/ForCustomBuild/SelectPcHeader.jsx new file mode 100644 index 0000000..ebfbbf6 --- /dev/null +++ b/client/src/AtomicComponents/ForCustomBuild/SelectPcHeader.jsx @@ -0,0 +1,14 @@ +import React from 'react'; + +function SelectPcHeader() { + return ( +
+

+ EASY{' '} + BUILDER +

+
+ ); +} + +export default SelectPcHeader; \ No newline at end of file diff --git a/client/src/AtomicComponents/ForProductForm/Category.jsx b/client/src/AtomicComponents/ForProductForm/Category.jsx new file mode 100644 index 0000000..c36dd33 --- /dev/null +++ b/client/src/AtomicComponents/ForProductForm/Category.jsx @@ -0,0 +1,533 @@ +const main = [ + { value: "Necessary", label: "Custom Build Necessary" }, + { value: "Optional", label: "Custom Build Optional" }, + { value: "Common", label: "Individual Category" } +] +const StockType = [ + { value: "", label: "All" }, + { value: "In Stock", label: "In Stock" }, + { value: "Low Stock", label: "Low Stock" }, + { value: "Out of Stock", label: "Out of Stock" } +]; + +const subCategories = { + Necessary: [ + { value: "ram", label: "Ram" }, + { value: "gpu", label: "Graphic Card" }, + { value: "processor", label: "Processor" }, + { value: "motherboard", label: "Motherboard" }, + { value: "storage", label: "Storage" }, + { value: "casing", label: "Casing" }, + { value: "power", label: "Power Supply" } + ], + Optional: [ + { value: "cooling", label: "Cooling" }, + { value: "keyboard", label: "Keyboard" }, + { value: "mouse", label: "Mouse" }, + { value: "monitor", label: "Monitor" }, + { value: "ups", label: "UPS" }, + { value: "expansion_network", label: "Expansion Card & Networking" }, + { value: "gamepad", label: "Gamepad" }, + ], + Common: [ + { value: "laptop", label: "Laptop" }, + { value: "prebuild", label: "Prebuild" }, + { value: "accessories", label: "Steaming Accessories" }, + { value: "externals", label: "External Storage" }, + { value: "cables_connectors", label: "Cables & Connectors" }, + + ] +}; + + + +const manufacture = { + processor: [ + { value: "intel", label: "Intel" }, + { value: "amd", label: "AMD" } + ], + ram: [ + { value: "Corsair", label: "Corsair" }, + { value: "team", label: "Team" }, + { value: "gskill", label: "GSKILL" }, + { value: "hyperx", label: "HyperX" }, + { value: "adata", label: "ADATA" }, + ], + motherboard: [ + { value: "asus", label: "ASUS" }, + { value: "gigabyte", label: "Gigabyte" }, + { value: "msi", label: "MSI" }, + ], + gpu: [ + { value: "nvidia", label: "NVIDIA" }, + { value: "amd", label: "AMD" }, + { value: "msi", label: "MSI" }, + { value: "zotac", label: "Zotac" }, + { value: "corsair", label: "Corsair" }, + { value: "asus", label: "ASUS" }, + + ], + storage: [ + { value: "Samsung", label: "Samsung" }, + { value: "seagate", label: "Seagate" }, + { value: "western_digital", label: "Western Digital" }, + { value: "toshiba", label: "Toshiba" }, + { value: "adata", label: "ADATA" }, + { value: "kingston", label: "Kingston" }, + ], + casing: [], + power: [], + cooling: [ + { value: "noctua", label: "Noctua" }, + { value: "corsair", label: "Corsair" }, + { value: "bequiet", label: "Be Quiet" }, + { value: "arctic", label: "Arctic" }, + { value: "coolerMaster", label: "Cooler Master" }, + { value: "nzxt", label: "NZXT" }, + { value: "adata", label: "Adata" }, + { value: "lian_li", label: "Lian Li" }, + { value: "antec", label: "Antec" } + ], + keyboard: [ + { value: "logitech", label: "Logitech" }, + { value: "hyperx", label: "HyperX" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "razer", label: "Razer" }, + { value: "asus", label: "ASUS" }, + ], + mouse: [ + { value: "logitech", label: "Logitech" }, + { value: "hyperx", label: "HyperX" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "razer", label: "Razer" }, + { value: "asus", label: "ASUS" }, + ], + monitor: [ + { value: "asus", label: "ASUS" }, + { value: "acer", label: "Acer" }, + { value: "dell", label: "Dell" }, + { value: "hp", label: "HP" }, + { value: "lenovo", label: "Lenovo" }, + ], + ups: [ + { value: "apc", label: "APC" }, + { value: "tripplite", label: "Tripplite" }, + { value: "cyberpowerpc", label: "CyberPowerPC" }, + ], + expansion_network: [], + gamepad: [], + laptop: [ + { value: "dell", label: "Dell" }, + { value: "lenovo", label: "Lenovo" }, + { value: "hp", label: "HP" }, + { value: "asus", label: "ASUS" }, + { value: "acer", label: "Acer" }, + { value: "msi", label: "MSI" }, + { value: "hp", label: "HP" }, + { value: "gigabyte", label: "Gigabyte" } + ], + prebuild: [ + { value: "dell", label: "Dell" }, + { value: "hp", label: "HP" }, + { value: "acer", label: "Acer" }, + { value: "lenovo", label: "Lenovo" }, + { value: "msi", label: "MSI" }, + { value: "asus", label: "ASUS" }, + ], +} + +const socketTypes = { + intel: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + { value: "lga1851", label: "LGA 1851" }, + ], + amd: [ + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" } + ] +} + +const cpuCores = [ + { value: 4, label: "4 Cores" }, + { value: 6, label: "6 Cores" }, + { value: 8, label: "8 Cores" }, + { value: 10, label: "10 Cores" }, + { value: 12, label: "12 Cores" }, + { value: 14, label: "14 Cores" }, + { value: 16, label: "16 Cores" }, + { value: 20, label: "20 Cores" }, + { value: 24, label: "24 Cores" } +]; + +const cpuThreads = [ + { value: 4, label: "4 Threads" }, + { value: 6, label: "6 Threads" }, + { value: 8, label: "8 Threads" }, + { value: 12, label: "12 Threads" }, + { value: 14, label: "14 Threads" }, + { value: 16, label: "16 Threads" }, + { value: 20, label: "20 Threads" }, + { value: 24, label: "24 Threads" }, + { value: 28, label: "28 Threads" }, + { value: 32, label: "32 Threads" }, + { value: 64, label: "64 Threads" }, +]; + +const ramAttributes = { + type: [ + { value: "ddr3", label: "DDR3" }, + { value: "ddr4", label: "DDR4" }, + { value: "ddr5", label: "DDR5" }, + { value: "lpddr4x", label: "LPDDR4X" }, + { value: "lpddr5", label: "LPDDR5" } + ], + speed: [ + { value: 2133, label: "2133 MHz" }, + { value: 2666, label: "2666 MHz" }, + { value: 3000, label: "3000 MHz" }, + { value: 3200, label: "3200 MHz" }, + { value: 3600, label: "3600 MHz" }, + { value: 4000, label: "4000 MHz" }, + { value: 4800, label: "4800 MHz" }, + { value: 5200, label: "5200 MHz" }, + { value: 5600, label: "5600 MHz" }, + { value: 6400, label: "6400 MHz" } + ], + size: [ + { value: 4, label: "4GB" }, + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + { value: 128, label: "128GB" } + ] +}; + +const motherboardAttributes = { + chipsets: [ + { value: "B550", label: "B550" }, + { value: "B650", label: "B650" }, + { value: "B660", label: "B660" }, + { value: "B660M", label: "B660M" }, + { value: "X570", label: "X570" }, + { value: "X670", label: "X670" }, + { value: "X670E", label: "X670E" }, + { value: "X670_PRO", label: "X670 PRO" }, + { value: "Z690", label: "Z690" }, + { value: "Z790", label: "Z790" }, + { value: "H610", label: "H610" }, + { value: "H670", label: "H670" }, + ], + motherboardSocket: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" } + ], + formFactor: [ + { value: "atx", label: "ATX" }, + { value: "micro_atx", label: "Micro ATX" }, + { value: "mini_itx", label: "Mini ITX" }, + { value: "e_atx", label: "E-ATX" }, + ], + ramSlots: [ + { value: 2, label: "2 Slots" }, + { value: 4, label: "4 Slots" }, + { value: 8, label: "8 Slots" }, + ], + maxRam: [ + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + { value: 128, label: "128GB" }, + { value: 256, label: "256GB" }, + ], + pcieSlotType: [ + { value: "pcie_x16", label: "PCIe x16" }, + { value: "pcie_x8", label: "PCIe x8" }, + { value: "pcie_x4", label: "PCIe x4" }, + { value: "pcie_x1", label: "PCIe x1" }, + ], + pcieVersion: [ + + ], + storageType: [ + { value: "SATA", label: "SATA" }, + { value: "M.2", label: "M.2" }, + { value: "SSD", label: "SSD" }, + ], + expansionSlots: [ + + ], + memoryTypes: [ + { value: "ddr3", label: "DDR3" }, + { value: "ddr4", label: "DDR4" }, + { value: "ddr5", label: "DDR5" }, + ], +}; + +const storageAttributes = { + storageTypes: [ + { value: "nvme_m2", label: "NVMe M.2" }, + { value: "sata_ssd", label: "SATA SSD" }, + { value: "hdd", label: "HDD" }, + { value: "m2_sata", label: "M.2 SATA" }, + { value: "sas_hdd", label: "SAS HDD" }, + { value: "pata_hdd", label: "PATA HDD" }, + ], + storageCapacities: [ + { value: 256, label: "256GB" }, + { value: 512, label: "512GB" }, + { value: 1000, label: "1TB" }, + { value: 2000, label: "2TB" }, + { value: 4000, label: "4TB" }, + { value: 8000, label: "8TB" }, + ], +}; + +const gpuAttributes = { + interfaceType: [ + { value: "pcie_4_0 x8", label: "PCIe 4.0 x8" }, + { value: "pcie_4_0 x16", label: "PCIe 4.0 x16" }, + { value: "pcie_5_0 x8", label: "PCIe 5.0 x8" }, + { value: "pcie_5_0 x16", label: "PCIe 5.0 x16" }, + { value: "agp", label: "AGP" }, + { value: "pci", label: "PCI" } + ], + powerConnectors: [ + { value: "6-pin", label: "1x6-pin" }, + { value: "8-pin", label: "1x8-pin" }, + { value: "6+8-pin", label: "6+8-pin" }, + { value: "2x8-pin", label: "2x8-pin" }, + { value: "12-pin", label: "2x6-pin" }, + { value: "16-pin", label: "16-pin (12VHPWR)" } + ], + gpuVram: [ + { value: "4", label: "4GB" }, + { value: "8", label: "8GB" }, + { value: "12", label: "12GB" }, + { value: "16", label: "16GB" }, + { value: "24", label: "24GB" }, + { value: "48", label: "48GB" } + ], + gpuSeries: [ + { value: "RTX 3060 Ti", label: "RTX 3060 Ti" }, + { value: "RTX 3080", label: "RTX 3080" }, + { value: "RTX 3080 Ti", label: "RTX 3080 Ti" }, + { value: "RTX 3090", label: "RTX 3090" }, + { value: "RTX 3090 Ti", label: "RTX 3090 Ti" }, + { value: "RTX 4060 Ti", label: "RTX 4060 Ti" }, + { value: "RTX 4070", label: "RTX 4070" }, + { value: "RTX 4070 Ti", label: "RTX 4070 Ti" }, + { value: "RTX 4080", label: "RTX 4080" }, + { value: "RTX 4090", label: "RTX 4090" }, + { value: "RTX 5070 Ti", label: "RTX 5070 Ti" }, + { value: "RTX 5080", label: "RTX 5080" }, + { value: "RX 6700 XT", label: "RX 6700 XT" }, + { value: "RX 6800", label: "RX 6800" }, + { value: "RX 6800 XT", label: "RX 6800 XT" }, + { value: "RX 6900 XT", label: "RX 6900 XT" }, + { value: "RX 7600", label: "RX 7600" }, + { value: "RX 6950 XT", label: "RX 6950 XT" } + ] +}; + +const casingAttributes = { + formFactor: [ + { value: "mid_tower", label: "Mid Tower" }, + { value: "full_tower", label: "Full Tower" }, + { value: "mini_tower", label: "Mini Tower" }, + { value: "cube", label: "Cube" }, + { value: "open_frame", label: "Open Frame" } + ], + supportedMotherboardSizes: [ + { value: "atx", label: "ATX" }, + { value: "micro_atx", label: "Micro-ATX" }, + { value: "mini_itx", label: "Mini-ITX" }, + { value: "e_atx", label: "E-ATX" }, + { value: "xl_atx", label: "XL-ATX" } + ], +}; + +const keyboardAttributes = { + manufacturer: [ + { value: "logitech", label: "Logitech" }, + { value: "razer", label: "Razer" }, + { value: "corsair", label: "Corsair" }, + { value: "steelseries", label: "SteelSeries" }, + { value: "coolermaster", label: "Cooler Master" } + ], + type: [ + { value: "mechanical", label: "Mechanical" }, + { value: "membrane", label: "Membrane" }, + { value: "hybrid", label: "Hybrid" } + ] +}; + +const mouseAttributes = { + type: [ + { value: "wired", label: "Wired" }, + { value: "wireless", label: "Wireless" }, + { value: "bluetooth", label: "Bluetooth" } + ], +}; + +const coolerAttributes = { + supportedSocket: [ + { value: "lga1200", label: "LGA 1200" }, + { value: "lga1151", label: "LGA 1151" }, + { value: "lga2066", label: "LGA 2066" }, + { value: "lga1700", label: "LGA 1700" }, + { value: "am4", label: "AM4" }, + { value: "tr4", label: "TR4" }, + { value: "am5", label: "AM5" }, + { value: "strx4", label: "sTRX4" }, + { value: "swrx8", label: "sWRX8" } + ], + coolerType: [ + { value: "air", label: "Air" }, + { value: "liquid", label: "Liquid" } + ] +}; + +const monitorAttributes = { + displaySize: [ + { value: 19, label: "19 inches" }, + { value: 20, label: "20 inches" }, + { value: 22, label: "22 inches" }, + { value: 24, label: "24 inches" }, + { value: 27, label: "27 inches" }, + { value: 32, label: "32 inches" }, + { value: 34, label: "34 inches" }, + { value: 42, label: "42 inches" } + ], + resolution: [ + { value: "1920x1080", label: "1920x1080 (Full HD)" }, + { value: "2560x1440", label: "2560x1440 (QHD)" }, + { value: "3840x2160", label: "3840x2160 (4K UHD)" }, + { value: "5120x1440", label: "5120x1440 (Super Ultra-Wide)" } + ], + refreshRate: [ + { value: 60, label: "60Hz" }, + { value: 75, label: "75Hz" }, + { value: 120, label: "120Hz" }, + { value: 144, label: "144Hz" }, + { value: 240, label: "240Hz" } + ], + panelType: [ + { value: "tn", label: "TN (Twisted Nematic)" }, + { value: "ips", label: "IPS (In-Plane Switching)" }, + { value: "va", label: "VA (Vertical Alignment)" }, + { value: "oled", label: "OLED" } + ], + monitorType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "office", label: "Office" }, + { value: "portable", label: "Portable" } + ] +}; + +const laptopAttributes = { + displaySize: [ + { value: 13, label: "13 inches" }, + { value: 14, label: "14 inches" }, + { value: 15.6, label: "15.6 inches" }, + { value: 16, label: "16 inches" }, + { value: 17, label: "17 inches" } + ], + resolution: [ + { value: "1920x1080", label: "1920x1080 (Full HD)" }, + { value: "2560x1600", label: "2560x1600 (WQXGA)" }, + { value: "2880x1800", label: "2880x1800 (2.8K)" }, + { value: "3840x2160", label: "3840x2160 (4K UHD)" } + ], + cpu: [ + { value: "intel_core_i3", label: "Intel Core i3" }, + { value: "intel_core_i5", label: "Intel Core i5" }, + { value: "intel_core_i7", label: "Intel Core i7" }, + { value: "intel_core_i9", label: "Intel Core i9" }, + { value: "amd_ryzen_5", label: "AMD Ryzen 5" }, + { value: "amd_ryzen_7", label: "AMD Ryzen 7" }, + { value: "amd_ryzen_9", label: "AMD Ryzen 9" } + ], + ram: [ + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" } + ], + storage: [ + { value: 256, label: "256GB" }, + { value: 512, label: "512GB" }, + { value: 1024, label: "1TB" }, + { value: 2048, label: "2TB" } + ], + laptopType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "personal", label: "Personal" } + ], + graphicCard: [ + { value: "intel_integrated", label: "Intel Integrated GPU" }, + { value: "amd_integrated", label: "AMD Integrated GPU" }, + { value: "nvidia_rtx_4060", label: "NVIDIA RTX 4060" }, + { value: "nvidia_rtx_4080", label: "NVIDIA RTX 4080" }, + { value: "amd_radeon_rx_7600", label: "AMD Radeon RX 7600" } + ] +}; + +const desktopAttributes = { + cpu: [ + { value: "intel_core_i7_11700f", label: "Intel Core i7-11700F" }, + { value: "intel_core_i5_13400", label: "Intel Core i5-13400" }, + { value: "intel_core_i9_13900k", label: "Intel Core i9-13900K" }, + { value: "amd_ryzen_5_7600x", label: "AMD Ryzen 5 7600X" }, + { value: "amd_ryzen_7_7800x3d", label: "AMD Ryzen 7 7800X3D" }, + { value: "amd_ryzen_9_7950x", label: "AMD Ryzen 9 7950X" } + ], + graphicCard: [ + { value: "nvidia_geforce_rtx_3080", label: "NVIDIA GeForce RTX 3080" }, + { value: "nvidia_geforce_rtx_4070", label: "NVIDIA GeForce RTX 4070" }, + { value: "nvidia_geforce_rtx_4090", label: "NVIDIA GeForce RTX 4090" }, + { value: "amd_radeon_rx_6800", label: "AMD Radeon RX 6800" }, + { value: "amd_radeon_rx_7900_xt", label: "AMD Radeon RX 7900 XT" }, + { value: "intel_arc_a770", label: "Intel Arc A770" } + ], + ram: [ + { value: 8, label: "8GB" }, + { value: 16, label: "16GB" }, + { value: 32, label: "32GB" }, + { value: 64, label: "64GB" }, + { value: 128, label: "128GB" } + ], + storage: [ + { value: 256, label: "256GB" }, + { value: 512, label: "512GB" }, + { value: 1024, label: "1TB" }, + { value: 2048, label: "2TB" }, + { value: 4096, label: "4TB" } + ], + desktopType: [ + { value: "gaming", label: "Gaming" }, + { value: "professional", label: "Professional" }, + { value: "personal", label: "Personal" }, + { value: "workstation", label: "Workstation" } + ] +}; + +// const allSubCategoryOptions = Object.values(subCategories).flatMap(options => options); + +export { main, StockType, subCategories, manufacture, socketTypes, cpuCores, cpuThreads, coolerAttributes, gpuAttributes, ramAttributes, motherboardAttributes, storageAttributes, casingAttributes, keyboardAttributes, mouseAttributes, monitorAttributes, laptopAttributes, desktopAttributes }; diff --git a/client/src/AtomicComponents/Icons/Iconset.jsx b/client/src/AtomicComponents/Icons/Iconset.jsx new file mode 100644 index 0000000..da4cf98 --- /dev/null +++ b/client/src/AtomicComponents/Icons/Iconset.jsx @@ -0,0 +1,98 @@ +import React from 'react'; +import EditIcon from "@mui/icons-material/Edit"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; +import SearchIcon from "@mui/icons-material/Search"; +import VisibilityIcon from "@mui/icons-material/Visibility"; +import DashboardIcon from "@mui/icons-material/Dashboard"; +import SettingsIcon from "@mui/icons-material/Settings"; +import PlaylistAddCheckIcon from '@mui/icons-material/PlaylistAddCheck'; +import ListAltIcon from '@mui/icons-material/ListAlt'; +import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +import DevicesIcon from '@mui/icons-material/Devices'; +import EventNoteIcon from '@mui/icons-material/EventNote'; +import ErrorIcon from '@mui/icons-material/Error'; +import QuestionAnswerIcon from '@mui/icons-material/QuestionAnswer'; +import TryIcon from '@mui/icons-material/Try'; +import DescriptionIcon from '@mui/icons-material/Description'; +import GroupIcon from "@mui/icons-material/Group"; +import FeedbackIcon from "@mui/icons-material/Feedback"; +import ReceiptLongIcon from '@mui/icons-material/ReceiptLong'; +import EditNoteIcon from '@mui/icons-material/EditNote'; +import PhoneIcon from "@mui/icons-material/Phone"; +import EmailIcon from "@mui/icons-material/Email"; +import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; +import PlaceIcon from "@mui/icons-material/Place"; +import NotificationsIcon from "@mui/icons-material/Notifications"; +import DarkModeIcon from "@mui/icons-material/DarkMode"; +import VpnKeyIcon from "@mui/icons-material/VpnKey"; +import CreateIcon from "@mui/icons-material/Create"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import DownloadIcon from "@mui/icons-material/Download"; +import MessageIcon from "@mui/icons-material/Message"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import MonetizationOnIcon from "@mui/icons-material/MonetizationOn"; +import HourglassEmptyIcon from "@mui/icons-material/HourglassEmpty"; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; +import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings'; +import AccountCircleIcon from '@mui/icons-material/AccountCircle'; +import PermMediaSharpIcon from '@mui/icons-material/PermMediaSharp'; +import AddPhotoAlternateSharpIcon from '@mui/icons-material/AddPhotoAlternateSharp'; + +export default function Iconset({ type = 'notification', fontSize = '30px', color }) { + const renderIcon = () => { + + switch (type) { + case 'photo': return ; + case 'image': return ; + case 'edit': return ; + case 'more': return ; + case 'delete': return ; + case 'add': return ; + case 'search': return ; + case 'view': return ; + case 'dashboard': return ; + case 'settings': return ; + case 'product': return ; + case 'order': return ; + case 'productList': return ; + case 'productCreate': return ; + case 'orderList': return ; + case 'receiveOrder': return ; + case 'comments': return ; + case 'RMA': return ; + case 'user-manage': return ; + case 'feedback-manage': return ; + case 'complains': return ; + case 'invoice': return ; + case 'invoiceList': return ; + case 'createInvoice': return ; + case 'call': return ; + case 'email': return ; + case 'calendar': return ; + case 'location': return ; + case 'notification': return ; + case 'darkmode': return ; + case 'key': return ; + case 'pen': return ; + case 'heart': return ; + case 'download': return ; + case 'message': return ; + case 'signout': return ; + case 'money': return ; + case 'pending': return ; + case 'cart': return ; + case 'admin': return ; + case 'profile': return ; + default: return null; + } + }; + return {renderIcon()}; +} + +//How to Use + +//import Iconset from "./AtomicComponents/Icons/Iconset"; +// //font size should be in pixels \ No newline at end of file diff --git a/client/src/AtomicComponents/Inputs/Input.jsx b/client/src/AtomicComponents/Inputs/Input.jsx new file mode 100644 index 0000000..37a44b0 --- /dev/null +++ b/client/src/AtomicComponents/Inputs/Input.jsx @@ -0,0 +1,338 @@ +import { + TextField, + MenuItem, + Autocomplete, + FormControl, + FormGroup, + FormControlLabel, + Checkbox, + Radio, + RadioGroup, + FormLabel, + FormHelperText, +} from "@mui/material"; +import React from "react"; +import InputAdornment from "@mui/material/InputAdornment"; +import { inputBaseClasses } from "@mui/material/InputBase"; + +export function InputField({ + label, + type = "text", + width = "180px", + rows, + color = "primary", + variant = "outlined", + fontSize = "16px", + helperText, + Placeholder, + error, + value, + Auto, + onChange = null, + row = false, + size = "medium", + options = [], + labelPlacement = "end", + disabled = false, +}) { + if (type === "text") { + return ( + { + if (onChange) onChange(e.target.value); + }} + slotProps={{ + input: { + endAdornment: ( + &`]: { + opacity: 1, + }, + }} + > + {Placeholder} + + ), + }, + }} + sx={{ + width: width, + marginBottom: "10px", + "& .MuiInputBase-input": { + fontSize: fontSize || "16px", + }, + "& .MuiInputLabel-root": { + fontSize: fontSize || "16px", + }, + "& .MuiInputBase-root": { + "& fieldset": { + borderWidth: 1, + borderRadius: 1, + }, + }, + }} + /> + ); + } + + if (type === "textarea") { + return ( + { + if (onChange) onChange(e.target.value); + }} + sx={{ + width: width, + marginBottom: "10px", + "& .MuiInputBase-input": { + fontSize: fontSize || "16px", + }, + "& .MuiInputLabel-root": { + fontSize: fontSize || "16px", + }, + "& .MuiInputBase-root": { + "& fieldset": { + borderWidth: 1, + borderRadius: 2, + }, + }, + }} + /> + ); + } + + if (type === "number") { + return ( + { + if (onChange) onChange(e.target.value); + }} + slotProps={{ + inputLabel: { + shrink: { Auto }, + }, + }} + disabled={disabled} + helperText={helperText} + sx={{ + width: width, + "& .MuiInputBase-input": { + fontSize: fontSize || "16px", + }, + "& .MuiInputLabel-root": { + fontSize: fontSize || "16px", + }, + "& .MuiInputBase-root": { + "& fieldset": { + borderWidth: 1, + borderRadius: 1, + }, + }, + }} + /> + ); + } + + if (type === "select") { + return ( + { + if (onChange) onChange(e.target.value); + }} + variant={variant} + color={color} + disabled={disabled} + error={!!error} + helperText={helperText} + sx={{ width }} + > + {options.map((option, index) => ( + + {option.label} + + ))} + + ); + } + + if (type === "autocomplete") { + return ( + option.label} + value={options.find((opt) => opt.value === value) || null} + onChange={(_, newValue) => { + onChange(newValue ? newValue.value : ""); + }} + disabled={disabled} + renderInput={(params) => ( + + )} + /> + ); + } + + if (type === "searchinput") { + return ( + option.label} + value={options.find((opt) => opt.value === value) || null} + onChange={(_, newValue) => { + onChange(newValue ? newValue.value : ""); + }} + disabled={disabled} + renderInput={(params) => ( + + )} + /> + ); + } + + if (type === "checkbox") { + return ( + + { + if (onChange) onChange(e.target.checked); + }} + size={size} + color={color} + disabled={disabled} + /> + } + label={label} + /> + {helperText && {helperText}} + + ); + } + + if (type === "radio") { + return ( + + {label} + onChange(e.target.value)} + > + {options.map((option, index) => ( + } + label={option.label} + labelPlacement={labelPlacement} + /> + ))} + + {helperText && {helperText}} + + ); + } +} + +// Usage: + +// for textField +// +// fontsize 14px or 16px +// variant - Standard, Outlined, Filled +// error +// width +// helperText + +// for select +// +// variant - Standard, Outlined, Filled +// error +// width +// helperText + +// for autocomplete +// +// width +// helperText + +// for checkbox +// +// width +// helperText +// size - small or large +// color + +// for radio +// + + + ), + }} + /> + ); +}; + +// How to use + +// diff --git a/client/src/AtomicComponents/Inputs/date.jsx b/client/src/AtomicComponents/Inputs/date.jsx new file mode 100644 index 0000000..7b93889 --- /dev/null +++ b/client/src/AtomicComponents/Inputs/date.jsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + + +export default function SetDate({ width, label, onChange }) { + return ( + + + + ); +} + +//How to use +// diff --git a/client/src/AtomicComponents/Typographics/TextStyles.jsx b/client/src/AtomicComponents/Typographics/TextStyles.jsx new file mode 100644 index 0000000..1e80ea2 --- /dev/null +++ b/client/src/AtomicComponents/Typographics/TextStyles.jsx @@ -0,0 +1,15 @@ +import { Typography } from '@mui/material' +import React from 'react' + +export function PageTitle({ value }) { + + return ( + + {value} + + ); +} + + + + diff --git a/client/src/AtomicComponents/theme.jsx b/client/src/AtomicComponents/theme.jsx new file mode 100644 index 0000000..3073bac --- /dev/null +++ b/client/src/AtomicComponents/theme.jsx @@ -0,0 +1,298 @@ +import { createTheme } from "@mui/material"; + +const theme = createTheme({ + palette: { + primary: { + main: "#8A00FC", + }, + primary100: { + main: "#F4E6FF", + }, + primary200: { + main: "#E8CCFE", + }, + primary300: { + main: "#DCB3FF", + }, + primary400: { + main: "#D099FE", + }, + primary500: { + main: "#C580FE", + }, + primary600: { + main: "#B966FD", + }, + primary700: { + main: "#AE4DFD", + }, + primary800: { + main: "#A133FD", + }, + primary900: { + main: "#961AFD", + }, + dark1: { + main: "#4D0A6E", + }, + dark2: { + main: "#1F012D", + }, + opacity10: { + main: "rgba(138, 0, 252, 0.1)", + }, + opacity20: { + main: "rgba(138, 0, 252, 0.2)", + }, + opacity30: { + main: "rgba(138, 0, 252, 0.3)", + }, + opacity40: { + main: "rgba(138, 0, 252, 0.4)", + }, + opacity50: { + main: "rgba(138, 0, 252, 0.5)", + }, + opacity60: { + main: "rgba(138, 0, 252, 0.6)", + }, + opacity70: { + main: "rgba(138, 0, 252, 0.7)", + }, + opacity80: { + main: "rgba(138, 0, 252, 0.8)", + }, + opacity90: { + main: "rgba(138, 0, 252, 0.9)", + }, + black: { + main: "#1C1919", + }, + black900: { + main: "#333030", + }, + black800: { + main: "#494747", + }, + black700: { + main: "#615E5E", + }, + black600: { + main: "#777575", + }, + black500: { + main: "#8E8C8C", + }, + black400: { + main: "#A4A3A3", + }, + black300: { + main: "#BBBABA", + }, + black200: { + main: "#D2D1D1", + }, + black100: { + main: "#E9E8E8", + }, + blackopacity10: { + main: "rgba(28, 25, 25, 0.1)", + }, + blackopacity20: { + main: "rgba(28, 25, 25, 0.2)", + }, + blackopacity30: { + main: "rgba(28, 25, 25, 0.3)", + }, + blackopacity40: { + main: "rgba(28, 25, 25, 0.4)", + }, + blackopacity50: { + main: "rgba(28, 25, 25, 0.5)", + }, + blackopacity60: { + main: "rgba(28, 25, 25, 0.6)", + }, + blackopacity70: { + main: "rgba(28, 25, 25, 0.7)", + }, + blackopacity80: { + main: "rgba(28, 25, 25, 0.8)", + }, + blackopacity90: { + main: "rgba(28, 25, 25, 0.9)", + }, + white: { + main: "#FFFFFF", + }, + white10: { + main: "rgba(255, 255, 255, 0.1)", + }, + white20: { + main: "rgba(255, 255, 255, 0.2)", + }, + white30: { + main: "rgba(255, 255, 255, 0.3)", + }, + white40: { + main: "rgba(255, 255, 255, 0.4)", + }, + white50: { + main: "rgba(255, 255, 255, 0.5)", + }, + white60: { + main: "rgba(255, 255, 255, 0.6)", + }, + white70: { + main: "rgba(255, 255, 255, 0.7)", + }, + white80: { + main: "rgba(255, 255, 255, 0.8)", + }, + white90: { + main: "rgba(255, 255, 255, 0.9)", + }, + white: { + main: '#FFFFFF' + }, + error: { + main: "#D91E18", + }, + success: { + main: "#4caf50", + }, + warning: { + main: "#FF9400", + }, + info: { + main: "#2C87C3", + }, + delete: { + main: '#ff5630', + }, + primaryprimary: { + main: '#961AFD', + contrastText: '#FFFFFF', + }, + primaryLight: { + main: '#B966FD', + contrastText: '#FFFFFF', + }, + primaryDark: { + main: '#7B16AE', + contrastText: '#FFFFFF', + }, + secondary: { + main: '#FFFFFF', + contrastText: '#1C1919', + }, + secondaryLight: { + main: '#FFFFFF', + contrastText: '#615E5E', + }, + secondaryDark: { + main: '#FFFFFF', + contrastText: '#961AFD' + }, + ternary: { + main: '#1C1919', + contrastText: '#FFFFFF', + }, + ternaryDark: { + main: '#797979', + contrastText: '#FFFFFF', + }, + }, + components: { + MuiButton: { + variants: [ + { + props: { variant: "customOutline" }, + style: { + textTransform: "none", + border: `2px solid #961AFD`, + color: "#961AFD", + backgroundColor: "#FFFFFF", + borderRadius: "8px", + borderWidth: "3px", + "&:hover": { + backgroundColor: "#F8F4FF", + }, + }, + }, + { + props: { variant: "text" }, + style: { + textTransform: "none", + color: "#961AFD", + backgroundColor: "#FFFFFF", + "&:hover": { + backgroundColor: "#e8dbff", + }, + }, + }, + ], + }, + + MuiListItemButton: { + styleOverrides: { + root: { + transition: "all 0.3s ease-in-out", + "&:hover": { + borderRadius: "0px", + }, + "&.Mui-selected": { + borderLeft: "5px solid #961AFD", + borderRadius: "0px", + }, + }, + }, + }, + }, + cssVariables: { + colorSchemeSelector: 'class', + }, + // colorSchemes: { light: true, dark: true }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +export default theme; + +// how to use colors +// InputProps={{ +// style: { +// color: theme.palette.error.main, // Text color +// }, +// }} +// sx={{ +// mb: 2, +// "& .MuiOutlinedInput-root": { +// "& fieldset": { +// borderColor: theme.palette.blacks.main, // Default border color +// }, +// "&:hover fieldset": { +// borderColor: theme.palette.primary.main, // Border color on hover +// }, +// "&.Mui-focused fieldset": { +// borderColor: theme.palette.primary[600], // Border color when focused (change to desired color) +// }, +// }, +// "& .MuiInputLabel-root": { +// color: theme.palette.blacks.main, // Default label color +// }, +// "& .MuiInputLabel-root.Mui-focused": { +// color: theme.palette.success.main, // Label color when focused (change to desired color) +// }, +// }} + +// or + +// color="error" diff --git a/client/src/Login/Forgetpassword.jsx b/client/src/Login/Forgetpassword.jsx new file mode 100644 index 0000000..c564f56 --- /dev/null +++ b/client/src/Login/Forgetpassword.jsx @@ -0,0 +1,121 @@ +import { Button, CircularProgress, TextField, Box, Typography, Card, Divider } from "@mui/material"; +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { toast } from "sonner"; +import axios from "axios"; +import { Link } from "react-router-dom"; +import pcImage from "../assets/PC.webp"; +import logo from '../assets/logo.png'; + +const ForgetPassword = () => { + const [email, setEmail] = useState(""); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + + const handleSubmit = async () => { + setLoading(true); + try { + await axios.post("http://localhost:8000/api/v1/users/forget-password", + { email }, + { withCredentials: true } + ); + toast.success("Reset OTP sent to email"); + navigate(`/auth/resetpassword?email=${encodeURIComponent(email)}`); + } catch (error) { + toast.error(error.response?.data?.message || "Failed to send reset email"); + } finally { + setLoading(false); + } + }; + + return ( + + + + {/* Left Section */} + + Logo + + Get compatible recommendations +
Pick your ideal components +
+ PC +
+ + {/* Vertical Divider */} + + + {/* Right Section */} + + + + + + Forgot Password + + + + + Enter your email to receive a password reset OTP + + +
+ {/* Email Field */} +
+ + setEmail(e.target.value)} + className="!bg-white !rounded" + InputProps={{ + className: "!h-8 !text-xs", + style: { borderRadius: '4px' } + }} + /> +
+ + {/* Submit Button */} + + + {/* Login Link */} + + Remember your password?{" "} + + Login here + + +
+
+
+
+ ); +}; + +export default ForgetPassword; diff --git a/client/src/Login/Login.jsx b/client/src/Login/Login.jsx new file mode 100644 index 0000000..a6de663 --- /dev/null +++ b/client/src/Login/Login.jsx @@ -0,0 +1,207 @@ +import React, { useState } from "react"; +import { + TextField, Button, CircularProgress, + Box, Typography, Card, Divider +} from "@mui/material"; +import { Google as GoogleIcon } from "@mui/icons-material"; +import { Link } from "react-router-dom"; +import axios from "axios"; +import { useDispatch } from "react-redux"; +import { setAuthUser } from "../Store/authSlice"; +import { useNavigate } from "react-router-dom"; +import { toast } from 'sonner'; +import logo from '../assets/logo.png'; +import pcImage from "../assets/PC.webp"; + +const Login = () => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + email: "", + password: "" + }); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const submitHandler = async (e) => { + e.preventDefault(); + setLoading(true); + + try { + const response = await axios.post( + "http://localhost:8000/api/v1/users/login", + formData, + { withCredentials: true } + ); + + const user = response.data.data.user; + localStorage.setItem('userId', user._id); + toast.success("Login successful!"); + dispatch(setAuthUser(user)); + localStorage.setItem('token', response.data.token); + + navigate(user.Role === "admin" ? '/dashboard' : '/user/complaint'); + + } catch (error) { + if (error.response) { + toast.error(error.response.data.message); + } else if (error.request) { + toast.error("Network error: Please check your connection"); + } else { + toast.error("An error occurred during login"); + } + } finally { + setLoading(false); + } + }; + + const handleGoogleLogin = () => { + window.open("http://localhost:8000/auth/google", "_self"); + }; + + return ( + + + + {/* Left Section */} + + Logo + + Get compatible recommendations +
Pick your ideal components +
+ PC +
+ + {/* Vertical Divider */} + + + {/* Right Section */} + + + + + + Login + + + +
+ {/* Email Field */} +
+ + +
+ + {/* Password Field */} +
+ + +
+ + {/* Forgot Password Link */} + + + Forgot Password? + + + + {/* Login Button */} + + + {/* Divider */} + + or + + + {/* Google Button */} + + + {/* Signup Link */} + + Don't have an account?{" "} + + Sign Up + + +
+
+
+
+ ); +}; + +export default Login; \ No newline at end of file diff --git a/client/src/Login/Resetpassword.jsx b/client/src/Login/Resetpassword.jsx new file mode 100644 index 0000000..38f690d --- /dev/null +++ b/client/src/Login/Resetpassword.jsx @@ -0,0 +1,166 @@ +import { Button, TextField, CircularProgress, Box, Card, Typography, Divider } from "@mui/material"; +import React, { useState } from "react"; +import { useSearchParams, useNavigate, Link } from "react-router-dom"; +import { useDispatch } from "react-redux"; +import { toast } from "sonner"; +import axios from "axios"; +import { setAuthUser } from "../Store/authSlice"; +import pcImage from "../assets/PC.webp"; +import logo from '../assets/logo.png'; + +const ResetPassword = () => { + const [otp, setOtp] = useState(""); + const [password, setPassword] = useState(""); + const [passwordConfirm, setPasswordConfirm] = useState(""); + const [loading, setLoading] = useState(false); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const email = searchParams.get("email"); + + const handleSubmit = async () => { + if (!otp || !email || !password || !passwordConfirm) { + toast.error("Please fill all fields"); + return; + } + + if (password !== passwordConfirm) { + toast.error("Passwords do not match"); + return; + } + + setLoading(true); + try { + const data = { email, otp, password, passwordConfirm }; + const response = await axios.post( + "http://localhost:8000/api/v1/users/reset-password", + data, + { withCredentials: true } + ); + + dispatch(setAuthUser(response.data.data.user)); + toast.success("Password reset successfully"); + navigate('/auth/login'); + } catch (error) { + toast.error(error.response?.data?.message || "Password reset failed"); + } finally { + setLoading(false); + } + }; + + return ( + + + + {/* Left Section */} + + Logo + + Get compatible recommendations +
Pick your ideal components +
+ PC +
+ + {/* Vertical Divider */} + + + {/* Right Section */} + + + + + + Reset Password + + + +
+ {/* OTP Field */} +
+ + setOtp(e.target.value)} + className="!bg-white !rounded" + inputProps={{ + inputMode: 'numeric', + pattern: '[0-9]*', + className: "!text-xs" + }} + /> +
+ + {/* Password Field */} +
+ + setPassword(e.target.value)} + className="!bg-white !rounded" + InputProps={{ className: "!text-xs" }} + /> +
+ + {/* Confirm Password Field */} +
+ + setPasswordConfirm(e.target.value)} + className="!bg-white !rounded" + InputProps={{ className: "!text-xs" }} + /> +
+ + {/* Submit Button */} + + + {/* Back Link */} + + + Back to Forgot Password + + +
+
+
+
+ ); +}; + +export default ResetPassword; \ No newline at end of file diff --git a/client/src/Login/Signup.jsx b/client/src/Login/Signup.jsx new file mode 100644 index 0000000..baea869 --- /dev/null +++ b/client/src/Login/Signup.jsx @@ -0,0 +1,267 @@ +import React, { useState } from "react"; +import { + TextField, Button, Checkbox, FormControlLabel, + CircularProgress, Box, Typography, Card, Divider +} from "@mui/material"; +import { Google as GoogleIcon } from "@mui/icons-material"; +import { Link } from "react-router-dom"; +import { useDispatch } from "react-redux"; +import { useNavigate } from "react-router-dom"; +import axios from "axios"; +import { toast } from 'sonner'; +import { setAuthUser } from "../Store/authSlice"; +import logo from '../assets/logo.png'; +import pcImage from "../assets/PC.webp"; + +const Signup = () => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + name: "", + email: "", + password: "", + passwordConfirm: "" + }); + const [termsAccepted, setTermsAccepted] = useState(false); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData({ ...formData, [name]: value }); + }; + + const submitHandler = async (e) => { + e.preventDefault(); + setLoading(true); + + if (!termsAccepted) { + toast.error("Please accept the terms and conditions"); + setLoading(false); + return; + } + + if (formData.password !== formData.passwordConfirm) { + toast.error("Passwords do not match"); + setLoading(false); + return; + } + + try { + const response = await axios.post( + "http://localhost:8000/api/v1/users/signup", + formData, + { withCredentials: true } + ); + + const user = response.data.data.user; + toast.success("Sign up successful!"); + dispatch(setAuthUser(user)); + navigate('/auth/verify'); + } catch (error) { + if (error.response) { + toast.error(error.response.data.message); + } else if (error.request) { + toast.error("Network error: Please check your connection"); + } else { + toast.error("An error occurred during signup"); + } + } finally { + setLoading(false); + } + }; + + const handleGoogleLogin = () => { + window.location.href = "http://localhost:8000/auth/google"; + }; + + return ( + + + + + {/* Left Section */} + + Logo + + Get compatible recommendations +
Pick your ideal components +
+ PC +
+ + {/* Vertical Divider */} + + + {/* Right Section */} + + + + + + Sign Up + + + +
+ {/* Form fields remain the same */} + {/* Full Name */} +
+ + +
+ + {/* Email */} +
+ + +
+ + {/* Password */} +
+ + +
+ + {/* Confirm Password */} +
+ + +
+ + {/* Terms Checkbox */} + setTermsAccepted(e.target.checked)} + sx={{ padding: '4px', paddingLeft: '10px' }} + /> + } + label={ + + Accept the T&C and have read the Privacy Policy + + } + className="!mt-2" + /> + + + {/* Sign Up Button - Changed to light blue */} + + + {/* Divider - Updated styling */} + + or + + + {/* Google Button Only */} + + + {/* Login Link */} + + Already have an account?{" "} + + Sign in + + + +
+
+
+ ); +}; + +export default Signup; \ No newline at end of file diff --git a/client/src/Login/Verify.jsx b/client/src/Login/Verify.jsx new file mode 100644 index 0000000..893f683 --- /dev/null +++ b/client/src/Login/Verify.jsx @@ -0,0 +1,199 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { + Button, Grid, Typography, Box, + TextField, CircularProgress, Card, Divider +} from '@mui/material'; +import { toast } from 'sonner'; +import axios from 'axios'; +import { useDispatch, useSelector } from 'react-redux'; +import { setAuthUser } from '../Store/authSlice'; +import { useNavigate } from 'react-router-dom'; +import pcImage from "../assets/PC.webp"; +import logo from '../assets/logo.png'; + +const Verify = () => { + const navigate = useNavigate(); + const dispatch = useDispatch(); + const [loading, setLoading] = useState(false); + const [otp, setOtp] = useState(['', '', '', '', '', '']); + const inputRefs = useRef([]); + const hiddenInputRef = useRef(null); + const user = useSelector((state) => state.auth.user); + + useEffect(() => { + if (!user) { + navigate('/auth/signup', { replace: true }); + } + }, [user, navigate]); + + const handlePaste = (e) => { + const pasteData = e.clipboardData.getData('text').slice(0, 6); + if (/^\d+$/.test(pasteData)) { + const newOtp = pasteData.split('').concat(Array(6 - pasteData.length).fill('')); + setOtp(newOtp); + + // Focus on last entered digit + const focusIndex = Math.min(pasteData.length - 1, 5); + inputRefs.current[focusIndex]?.focus(); + } + }; + + const handleChange = (index, event) => { + const { value } = event.target; + if (/^\d{0,1}$/.test(value)) { + const newOtp = [...otp]; + newOtp[index] = value; + setOtp(newOtp); + + if (value.length === 1 && index < 5) { + inputRefs.current[index + 1]?.focus(); + } + } + }; + + const handleKeyDown = (index, event) => { + const { key } = event; + if (key === 'Backspace' && !otp[index] && index > 0) { + inputRefs.current[index - 1]?.focus(); + } + }; + + const handleSubmit = async () => { + setLoading(true); + try { + const otpValue = otp.join(''); + const response = await axios.post( + 'http://localhost:8000/api/v1/users/verify', + { otp: otpValue }, + { withCredentials: true } + ); + + dispatch(setAuthUser(response.data.data.user)); + toast.success('Verification successful'); + navigate('/auth/login'); + } catch (error) { + toast.error(error.response?.data?.message || 'Verification failed'); + } finally { + setLoading(false); + } + }; + + const handleResendOtp = async () => { + setLoading(true); + try { + await axios.post('http://localhost:8000/api/v1/users/resend-otp', null, { withCredentials: true }); + toast.success('New OTP sent to your email'); + } catch (error) { + toast.error(error.response?.data?.message || 'Resend failed'); + } finally { + setLoading(false); + } + }; + + return ( + + + + {/* Left Section */} + + Logo + + Get compatible recommendations +
Pick your ideal components +
+ PC +
+ {/* Vertical Divider */} + + + {/* Right Section */} + + + + + + Verify Your Email + + + + {/* Hidden input for paste functionality */} + + + + Enter the 6-digit code sent to your email + + + + {otp.map((digit, index) => ( + + handleChange(index, e)} + onKeyDown={(e) => handleKeyDown(index, e)} + inputRef={(el) => (inputRefs.current[index] = el)} + onFocus={() => hiddenInputRef.current?.focus()} + type="text" + inputProps={{ + maxLength: 1, + className: "!text-center !text-xl", + }} + className="!bg-white !rounded" + sx={{ + width: '50px', + '& .MuiInputBase-root': { + height: '50px' + } + }} + /> + + ))} + + + + + + + + +
+
+ ); +}; + +export default Verify; diff --git a/client/src/MoleculesComponents/AdminNavigationbar.jsx b/client/src/MoleculesComponents/AdminNavigationbar.jsx new file mode 100644 index 0000000..afe77f3 --- /dev/null +++ b/client/src/MoleculesComponents/AdminNavigationbar.jsx @@ -0,0 +1,129 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { createTheme } from '@mui/material/styles'; +import DashboardIcon from '@mui/icons-material/Dashboard'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; +import BarChartIcon from '@mui/icons-material/BarChart'; +import DescriptionIcon from '@mui/icons-material/Description'; +import LayersIcon from '@mui/icons-material/Layers'; +import { AppProvider } from '@toolpad/core/AppProvider'; +import { DashboardLayout } from '@toolpad/core/DashboardLayout'; +import { useDemoRouter } from '@toolpad/core/internal'; + +const NAVIGATION = [ + { + kind: 'header', + title: 'Main items', + }, + { + segment: 'dashboard', + title: 'Dashboard', + icon: , + }, + { + segment: 'orders', + title: 'Orders', + icon: , + }, + { + kind: 'divider', + }, + { + kind: 'header', + title: 'Analytics', + }, + { + segment: 'reports', + title: 'Reports', + icon: , + children: [ + { + segment: 'sales', + title: 'Sales', + icon: , + }, + { + segment: 'traffic', + title: 'Traffic', + icon: , + }, + ], + }, + { + segment: 'integrations', + title: 'Integrations', + icon: , + }, +]; + +const demoTheme = createTheme({ + cssVariables: { + colorSchemeSelector: 'data-toolpad-color-scheme', + }, + colorSchemes: { light: true, dark: true }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutBasic(props) { + const { window } = props; + + const router = useDemoRouter('/dashboard'); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + + + + + + // preview-end + ); +} + +DashboardLayoutBasic.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutBasic; \ No newline at end of file diff --git a/client/src/MoleculesComponents/Admin_components/AccountDropdown.jsx b/client/src/MoleculesComponents/Admin_components/AccountDropdown.jsx new file mode 100644 index 0000000..41fc583 --- /dev/null +++ b/client/src/MoleculesComponents/Admin_components/AccountDropdown.jsx @@ -0,0 +1,58 @@ +import { useState } from 'react'; +import { Menu, MenuItem, IconButton, Avatar, Divider } from '@mui/material'; +import { useNavigate } from 'react-router-dom'; +import Iconset from '../../AtomicComponents/Icons/Iconset'; + +const AccountDropdown = () => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const navigate = useNavigate(); + + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleNavigation = (path) => { + navigate(path); + handleClose(); + }; + + return ( + <> + + + + + handleNavigation('/admin/profile')}> + Profile + + handleNavigation('/admin/setting')}> + Settings + + + handleNavigation('/logout')}> + Logout + + + + ); +}; + +export default AccountDropdown; diff --git a/client/src/MoleculesComponents/Admin_components/ImageSelector.jsx b/client/src/MoleculesComponents/Admin_components/ImageSelector.jsx new file mode 100644 index 0000000..a4b8da4 --- /dev/null +++ b/client/src/MoleculesComponents/Admin_components/ImageSelector.jsx @@ -0,0 +1,104 @@ +import React, { useState, useRef, forwardRef, useImperativeHandle } from 'react' +import Iconset from '../../AtomicComponents/Icons/Iconset'; +import { Typography } from '@mui/material'; + +// Use forwardRef to allow the parent to access internal methods +const ImageSelector = forwardRef(({ onImagesSelect }, ref) => { + const [images, setImages] = useState([]) + const [isDragging, setIsDragging] = useState(false); + const fileInputRef = useRef() + + // Expose the deleteAllImages method to the parent + useImperativeHandle(ref, () => ({ + deleteAllImages + })); + + function selectFiles() { + fileInputRef.current.click(); + } + function onFileSelect(event) { + const files = event.target.files; + if (!files || files.length === 0) return; + + const newImages = Array.from(files) + .filter((file) => file.type.startsWith('image/')) + .filter((file) => !images.some((e) => e.name === file.name)) // Avoid duplicates + .map((file) => ({ + name: file.name, + src: URL.createObjectURL(file), + file: file, + })); + + const updatedImages = [...images, ...newImages].slice(0, 4); + setImages(updatedImages); + + onImagesSelect(updatedImages.map((img) => img.file)); + } + function deleteImage(index) { + const updatedImages = images.filter((_, i) => i !== index); + setImages(updatedImages); + onImagesSelect(updatedImages.map((img) => img.file)); + } + function deleteAllImages() { + setImages([]); + onImagesSelect([]); + } + function onDragOver(event) { + event.preventDefault() + setIsDragging(true) + event.dataTransfer.dropEffect = 'copy' + } + function onDragLeave(event) { + event.preventDefault() + setIsDragging(false) + } + function onDrop(event) { + event.preventDefault(); + setIsDragging(false); + onFileSelect({ target: { files: event.dataTransfer.files } }); + } + return ( +
+
+ {isDragging ? ( +
+ + Drag your images here +
+ + ) : ( + <> +
+
Drop or select file
+ Drag file here or click to {''} + + browse + + {' '} through your device + + )} + +
+
+ {Array.isArray(images) && images.map((image, index) => ( +
+
deleteImage(index)} + className="delete z-999 text-violet-700 cursor-pointer text-xl absolute -top-1 right-1" + > + × +
+
+ {image.name} +
+
+ ))} +
+
+ ); +}); +export default ImageSelector; diff --git a/client/src/MoleculesComponents/Table.jsx b/client/src/MoleculesComponents/Table.jsx new file mode 100644 index 0000000..4b11499 --- /dev/null +++ b/client/src/MoleculesComponents/Table.jsx @@ -0,0 +1,135 @@ +import React from "react"; +import { + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TablePagination, + Paper, + IconButton, +} from "@mui/material"; +import theme from "../AtomicComponents/theme.jsx"; +import Iconset from "../AtomicComponents/Icons/Iconset.jsx"; + +export function UserTable({ columns, data, iconTypes = [], iconActions = {}, width, color }) { + + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + } + const autoSizeCellStyle = { + padding: "8px 16px", // Ensure consistent padding + whiteSpace: "nowrap", + Maxwidth: "50%", + }; + + return ( + + + + + + {columns.map((column) => ( + + {column.label} + + ))} + + + + + {data + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row, index) => ( + + {columns.map((column) => ( + + {row[column.id]} + + ))} + {iconTypes.length > 0 && ( + + {iconTypes.map((type, idx) => ( + iconActions[type] && iconActions[type](row.id)} + translate="3s" + sx={{ + "&:hover": { + color: theme.palette.primary.main, // Change icon color on hover + opacity: 0.9, // Change icon opacity on hover + }, + }} + > + + + ))} + + )} + + ))} + +
+
+ +
+ ); +}; + + +// How to Use + + // const userColumns = [ + // { id: "userCard", label: "User" }, + // { id: "phone", label: "Phone Number" }, + // { id: "registrationDate", label: "Registration Date" }, + // { id: "status", label: "Status" }, + // ]; + + // const userData = [ + // { + // userCard: , + // phone: "+46 8 123 456", + // registrationDate: "2024-11-07", + // status: "Banned", + // }, + // { + // userCard: , + // phone: "+54 11 1234-5678", + // registrationDate: "2024-11-08", + // status: "Inactive", + // }, + // ]; + + // const iconTypes = ["edit", "more"]; + +// return ( + // + // + // +// ); diff --git a/client/src/MoleculesComponents/ToolpadFixer.jsx b/client/src/MoleculesComponents/ToolpadFixer.jsx new file mode 100644 index 0000000..863ab56 --- /dev/null +++ b/client/src/MoleculesComponents/ToolpadFixer.jsx @@ -0,0 +1,188 @@ +import Iconset from "../AtomicComponents/Icons/Iconset"; +import theme from "../AtomicComponents/theme"; +import { DashboardLayout } from "@toolpad/core"; + +const NAVIGATION = [ + { + kind: "header", + title: "Main", + }, + { + segment: "dashboard", + title: "Dashboard", + icon: , + }, + { + segment: "admin", + title: "Admin", + icon: , + children: [ + { + segment: "profile", + title: "Profile", + icon: , + }, + { + segment: "setting", + title: "Settings", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: 'header', + title: 'Games', + }, + { + segment: 'games', + title: 'Games', + icon: , // Reuse an existing icon or create a new one + children: [ + { + segment: 'managegames', + title: 'Manage Games', + icon: , // Reuse or replace with a game-specific icon + }, + { + segment: 'creategame', + title: 'Create Game', + icon: , // Reuse or replace with a game-specific icon + }, + ], + }, + + + { + kind: "header", + title: "Product & Order", + }, + { + segment: "products", + title: "Products", + icon: , + children: [ + { + segment: "manageproduct", + title: "Manage Product", + icon: , + }, + { + segment: "createproduct", + title: "Create Product", + icon: , + }, + ], + }, + { + segment: "orders", + title: "Orders ", + icon: , + children: [ + { + segment: "orderlist", + title: "Order List", + icon: , + }, + { + segment: "receiveorder", + title: "Received Order", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: "header", + title: "User Section", + }, + { + segment: "usermanage", + title: "User Manage", + icon: , + }, + { + kind: "divider", + }, + { + kind: "header", + title: "Feedbacks", + }, + { + segment: "feedbackmanage", + title: "Feedback Manage", + icon: , + children: [ + { + segment: "complaints", + title: "Complaints", + icon: , + }, + { + segment: "comments&reviews", + title: "Comments & Reviews", + icon: , + }, + { + segment: "rma", + title: "RMA", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: "header", + title: "Invoices", + }, + { + segment: "invoice", + title: "Invoice ", + icon: , + children: [ + { + segment: "invoicelist", + title: "Invoice List", + icon: , + }, + { + segment: "invoicecreate", + title: "Create Invoice", + icon: , + }, + ], + }, +]; + +export default function ToolpadFixer() { + return ( + + ), + title: "", + }} + theme={theme} + > + + + ); +} \ No newline at end of file diff --git a/client/src/MoleculesComponents/User_component/Footer.jsx b/client/src/MoleculesComponents/User_component/Footer.jsx new file mode 100644 index 0000000..083a796 --- /dev/null +++ b/client/src/MoleculesComponents/User_component/Footer.jsx @@ -0,0 +1,112 @@ +import { Facebook, Instagram, YouTube, Google, Twitter } from "@mui/icons-material"; + +export default function Footer() { + return ( + + ); +} diff --git a/client/src/MoleculesComponents/User_component/Navbar.jsx b/client/src/MoleculesComponents/User_component/Navbar.jsx new file mode 100644 index 0000000..274922b --- /dev/null +++ b/client/src/MoleculesComponents/User_component/Navbar.jsx @@ -0,0 +1,107 @@ +import { useState, useEffect } from "react"; +import { HelpOutline, ShoppingCart, AccountCircle } from "@mui/icons-material"; + +export default function Navbar() { + const [openDropdown, setOpenDropdown] = useState(null); + + // Close dropdown when clicking outside + useEffect(() => { + const handleClickOutside = (event) => { + if (!event.target.closest(".dropdown-container")) { + setOpenDropdown(null); + } + }; + document.addEventListener("click", handleClickOutside); + return () => document.removeEventListener("click", handleClickOutside); + }, []); + + return ( + + ); +} diff --git a/client/src/MoleculesComponents/User_navbar_and_footer/Footer.jsx b/client/src/MoleculesComponents/User_navbar_and_footer/Footer.jsx new file mode 100644 index 0000000..079d74e --- /dev/null +++ b/client/src/MoleculesComponents/User_navbar_and_footer/Footer.jsx @@ -0,0 +1,112 @@ +import { Facebook, Instagram, YouTube, Google, Twitter } from "@mui/icons-material"; + +export default function Footer() { + return ( + + ); +} diff --git a/client/src/MoleculesComponents/User_navbar_and_footer/Navbar.jsx b/client/src/MoleculesComponents/User_navbar_and_footer/Navbar.jsx new file mode 100644 index 0000000..34a40e2 --- /dev/null +++ b/client/src/MoleculesComponents/User_navbar_and_footer/Navbar.jsx @@ -0,0 +1,227 @@ +import { useSelector } from "react-redux"; + +import { useState, useEffect } from "react"; +import { HelpOutline, ShoppingCart, AccountCircle } from "@mui/icons-material"; +import { Link } from "react-router-dom"; +import Usersearchbar from "./Usersearchbar"; + + + + + + + + + + + + +export default function Navbar() { + + const cartItems = useSelector(state => state.cart?.cartItems) || []; + + + + + const [openDropdown, setOpenDropdown] = useState(null); + + // Close dropdown when clicking outside + + + useEffect(() => { + const handleClickOutside = (event) => { + if (!event.target.closest(".dropdown-container")) { + setOpenDropdown(null); + } + }; + + + document.addEventListener("click", handleClickOutside); + return () => document.removeEventListener("click", handleClickOutside); + }, []); + + + + + return ( + + ); +} diff --git a/client/src/MoleculesComponents/User_navbar_and_footer/Usersearchbar.jsx b/client/src/MoleculesComponents/User_navbar_and_footer/Usersearchbar.jsx new file mode 100644 index 0000000..c573b12 --- /dev/null +++ b/client/src/MoleculesComponents/User_navbar_and_footer/Usersearchbar.jsx @@ -0,0 +1,36 @@ +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; + +export default function SearchBar() { + const [query, setQuery] = useState(""); + const navigate = useNavigate(); + + const handleSearch = (e) => { + e.preventDefault(); + if (query.trim()) { + navigate(`/search?query=${query}`); // Redirects to Search Results Page + } + }; + return ( +
+
+ {/* Search Input */} + setQuery(e.target.value)} + className="w-full p-[10px] pl-4 text-black rounded-full bg-white border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 sm:pr-20" + /> + + {/* Search Button */} + +
+
+ ); +} diff --git a/client/src/Store/authSlice.js b/client/src/Store/authSlice.js new file mode 100644 index 0000000..d4b4429 --- /dev/null +++ b/client/src/Store/authSlice.js @@ -0,0 +1,21 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const initialState = { + user: null, +}; + +const authSlice = createSlice({ + name: "auth", + initialState, + reducers: { + setAuthUser: (state, action) => { + state.user = action.payload; + }, + logout: (state) => { + state.user = null; + }, + }, +}); + +export const { setAuthUser, logout } = authSlice.actions; +export default authSlice.reducer; diff --git a/client/src/Store/formSlice.js b/client/src/Store/formSlice.js new file mode 100644 index 0000000..3b05d38 --- /dev/null +++ b/client/src/Store/formSlice.js @@ -0,0 +1,46 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { subCategories, manufacture, socketTypes } from "../AtomicComponents/ForProductForm/Category"; + +const initialState = { + selectedMainCategory: "", + selectedSubCategory: "", + selectedManufacture: "", + subCategoryOptions: [subCategories], + manufactureOptions: [manufacture], + socketTypeOptions: [socketTypes], + +}; + +const formSlice = createSlice({ + name: "form", + initialState, + reducers: { + setSelectedMainCategory: (state, action) => { + state.selectedMainCategory = action.payload; + // Update subcategory options based on the selected main category + state.subCategoryOptions = subCategories[action.payload] || []; + }, + setSelectedSubCategory: (state, action) => { + state.selectedSubCategory = action.payload; + // Update manufacture options based on the selected subcategory + state.manufactureOptions = manufacture[action.payload] || []; + }, + setSelectedManufacture: (state, action) => { + state.selectedManufacture = action.payload; + // Update socket type options based on the selected manufacture + state.socketTypeOptions = socketTypes[action.payload] || []; + }, + resetForm: (state) => { + return initialState; // Reset state to initial values + } + }, +}); + +export const { + setSelectedMainCategory, + setSelectedSubCategory, + setSelectedManufacture, + resetForm, +} = formSlice.actions; + +export default formSlice.reducer; \ No newline at end of file diff --git a/client/src/Store/productSlice.js b/client/src/Store/productSlice.js new file mode 100644 index 0000000..644251d --- /dev/null +++ b/client/src/Store/productSlice.js @@ -0,0 +1,37 @@ +// src/store/productSlice.js +import { createSlice } from '@reduxjs/toolkit'; + +const initialState = { + title: "", + content: "", + mainCategory: "", + subCategory: "", + manufacture: "", + socketType: "", + tdp: 0, + cores: 0, + threads: 0, + baseClock: 0, + boostClock: 0, + integratedGraphics: false, + includesCooler: false, + memoryType: "", + memoryCapacity: 0, + memorySpeed: 0, + quantity: 0, + price: 0, +}; + +const productSlice = createSlice({ + name: 'product', + initialState, + reducers: { + updateProduct: (state, action) => { + return { ...state, ...action.payload }; + }, + resetProduct: () => initialState, + }, +}); + +export const { updateProduct, resetProduct } = productSlice.actions; +export default productSlice.reducer; \ No newline at end of file diff --git a/client/src/Store/store.js b/client/src/Store/store.js new file mode 100644 index 0000000..b8f8ccd --- /dev/null +++ b/client/src/Store/store.js @@ -0,0 +1,49 @@ +import { configureStore, combineReducers } from '@reduxjs/toolkit'; +import authSlice from './authSlice'; +import formSlice from './formSlice'; +import productSlice from './productSlice'; +import cartSlice from '../redux/cartSlice'; + + +import { + persistReducer, + FLUSH, + REHYDRATE, + PAUSE, + PERSIST, + PURGE, + REGISTER, +} from 'redux-persist'; +import storage from 'redux-persist/lib/storage'; + +const persistConfig = { + key: 'root', + version: 1, // Specify the version of your persisted state + storage, // Use localStorage + // Only persist certain reducers, or leave empty to persist all + whitelist: ['auth', 'form', 'product'] +}; + +const rootReducer = combineReducers({ + auth: authSlice, + form: formSlice, + product: productSlice, + cart : cartSlice, + // Add your slices here + // Add other reducers here as needed +}); + +const persistedReducer = persistReducer(persistConfig, rootReducer); + +const store = configureStore({ + reducer: persistedReducer, // Use the persisted reducer here + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: { + ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], + }, + }), +}); + +// Export the store +export default store; diff --git a/client/src/User/ComplaintSubmit.jsx b/client/src/User/ComplaintSubmit.jsx new file mode 100644 index 0000000..be2dd21 --- /dev/null +++ b/client/src/User/ComplaintSubmit.jsx @@ -0,0 +1,144 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { toast } from 'sonner'; +import { useNavigate } from 'react-router-dom'; +import { Button, TextField, Box, Container, MenuItem, Select, InputLabel, FormControl } from '@mui/material'; + +const ComplaintSubmit = () => { + const navigate = useNavigate(); + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [complaintType, setComplaintType] = useState(''); + const userId = localStorage.getItem('userId'); + + const history = () => { + navigate('/user/complaintHistory'); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + if (!userId) { + alert('You need to be logged in!'); + return; + } + + try { + await axios.post('http://localhost:8000/api/complaints/submit', { + title, description, complaintType, userId + }); + toast.success('Complaint submitted successfully!'); + navigate('/user/complaintHistory'); + } catch (err) { + toast.error('Failed to submit complaint'); + } + }; + + return ( + + + + +
+ setTitle(e.target.value)} + sx={{ + marginTop: '2rem', + marginBottom: '2rem', // Increased margin + + }} + + /> + + + Complaint Type + + + + setDescription(e.target.value)} + sx={{ + marginBottom: '2rem', // Increased margin + + }} + + /> + + + +
+
+ ); +}; + +export default ComplaintSubmit; diff --git a/client/src/User/UserComplaints.jsx b/client/src/User/UserComplaints.jsx new file mode 100644 index 0000000..6e4c4b8 --- /dev/null +++ b/client/src/User/UserComplaints.jsx @@ -0,0 +1,167 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import { + Container, + Typography, + Card, + CardContent, + Chip, + Stack, + Skeleton, + useTheme +} from '@mui/material'; +import { CheckCircle, Error, HourglassTop } from '@mui/icons-material'; + +const UserComplaints = () => { + const [complaints, setComplaints] = useState([]); + const [loading, setLoading] = useState(true); + const userId = localStorage.getItem('userId') || null; + const token = localStorage.getItem('token'); + const theme = useTheme(); + + const statusConfig = { + pending: { color: theme.palette.warning.main, icon: }, + resolved: { color: theme.palette.success.main, icon: }, + rejected: { color: theme.palette.error.main, icon: } + }; + + useEffect(() => { + const fetchComplaints = async () => { + if (!userId) return; + + try { + const response = await axios.get(`http://localhost:8000/api/complaints/user/${userId}`, { + headers: { Authorization: `Bearer ${token}` }, + }); + setComplaints(response.data); + } catch (err) { + console.error('Failed to fetch complaints:', err); + } finally { + setLoading(false); + } + }; + + fetchComplaints(); + }, [userId, token]); + + const getStatusChip = (status) => ( + + ); + + if (loading) { + return ( + + {[...Array(3)].map((_, index) => ( + + ))} + + ); + } + + return ( + + + Complaint History + + + {complaints.length === 0 ? ( + + + + No complaints found + + + ) : ( + complaints.map((complaint) => ( + + + + + {complaint.title} + + {getStatusChip(complaint.status)} + + + + + + {new Date(complaint.createdAt).toLocaleDateString()} + + + + + {complaint.description} + + + {complaint.response && ( + + + Admin Response: + + + {complaint.response} + + + )} + + + )) + )} + + ); +}; + +export default UserComplaints; diff --git a/client/src/UserdashboardFeature/PublishedBuildsContent.jsx b/client/src/UserdashboardFeature/PublishedBuildsContent.jsx new file mode 100644 index 0000000..d4b4f9b --- /dev/null +++ b/client/src/UserdashboardFeature/PublishedBuildsContent.jsx @@ -0,0 +1,49 @@ +import React from "react"; +import PublishedBuildCard from "../AtomicComponents/Cards/PublishedBuildCard"; + +export default function PublishedBuildsContent() { + return ( +
+ + + + + +
+ ); +} diff --git a/client/src/UserdashboardFeature/SideNav.jsx b/client/src/UserdashboardFeature/SideNav.jsx new file mode 100644 index 0000000..a52b4d9 --- /dev/null +++ b/client/src/UserdashboardFeature/SideNav.jsx @@ -0,0 +1,255 @@ +import React from "react"; +import { + List, + ListItem, + ListItemText, + ListItemButton, + ListItemIcon, +} from "@mui/material"; +import { Link } from "react-router-dom"; +import { Mail as MailIcon, Inbox as InboxIcon } from "@mui/icons-material"; + +export default function SideNav() { + return ( + + ); +} + +// import * as React from "react"; +// import PropTypes from "prop-types"; +// import { useNavigate } from "react-router-dom"; +// import { +// Box, +// AppBar, +// CssBaseline, +// Divider, +// Drawer, +// List, +// ListItem, +// ListItemButton, +// ListItemIcon, +// ListItemText, +// Toolbar, +// } from "@mui/material"; +// import DensityMediumSharpIcon from "@mui/icons-material/DensityMediumSharp"; +// import { +// MoveToInbox as InboxIcon, +// Mail as MailIcon, +// Menu as MenuIcon, +// PersonOutlineOutlined as PersonOutlineOutlinedIcon, +// } from "@mui/icons-material"; + +// const drawerWidth = 240; + +// function SideNav(props) { +// const { window } = props; +// const [mobileOpen, setMobileOpen] = React.useState(false); +// const [isClosing, setIsClosing] = React.useState(false); +// const navigate = useNavigate(); + +// const handleDrawerClose = () => { +// setIsClosing(true); +// setMobileOpen(false); +// }; + +// const handleDrawerTransitionEnd = () => { +// setIsClosing(false); +// }; + +// const handleDrawerToggle = () => { +// if (!isClosing) { +// setMobileOpen(!mobileOpen); +// } +// }; + +// const drawer = ( +//
+// +// +// +// navigate("/profile")}> +// +// +// +// +// +// +// +// navigate("/savedBuilds")}> +// +// +// +// +// +// +// +// navigate("/myOrders")}> +// +// +// +// +// +// +// +// +// +// +// navigate("/settings")}> +// +// +// +// +// +// +// +// +//
+// ); + +// // Remove this const when copying and pasting into your project. +// const container = +// window !== undefined ? () => window().document.body : undefined; + +// return ( +// +// + +// +// +// + +// +// {/* The implementation can be swapped with js to avoid SEO duplication of links. */} +// +// {drawer} +// +// +// {drawer} +// +// +// +// +// ); +// } + +// SideNav.propTypes = { +// /** +// * Injected by the documentation to work in an iframe. +// * Remove this when copying and pasting into your project. +// */ +// window: PropTypes.func, +// }; + +// export default SideNav; diff --git a/client/src/UserdashboardFeature/pages/CustomBuildsContent.jsx b/client/src/UserdashboardFeature/pages/CustomBuildsContent.jsx new file mode 100644 index 0000000..adb15e8 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/CustomBuildsContent.jsx @@ -0,0 +1,41 @@ +import React from "react"; +import PCBuildCard from "../../AtomicComponents/Cards/PCBuildCard"; + +export default function CustomBuildsContent() { + const pcBuild = { + image: + "https://buildmypc.lk/wp-content/uploads/2024/05/Amethyst-GAming-PC-Build-MY-PC-600x600.jpg", // Replace with a real image URL + name: "PC Build 1", + score: 1400, + specs: [ + ["OS", "Windows 11 Home"], + ["Processor", "Intel® Core™ i9-14900KF CPU"], + ["Motherboard", "ASUS Z790 Gaming WiFi 7"], + ["Memory", "32GB DDR5-600MHz RGB RAM"], + ["Graphics", "GeForce RTX 4070 Ti SUPER - 16GB"], + ["Storage", "2TB M.2 NVMe Gen4 SSD"], + ], + }; + return ( +
+ + + +
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/MyOrders.jsx b/client/src/UserdashboardFeature/pages/MyOrders.jsx new file mode 100644 index 0000000..7d57fa4 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/MyOrders.jsx @@ -0,0 +1,140 @@ +import React, { useState } from "react"; +import SideNav from "../SideNav"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import { Box } from "@mui/material"; +import Tab from "@mui/material/Tab"; +import TabContext from "@mui/lab/TabContext"; +import TabList from "@mui/lab/TabList"; +import TabPanel from "@mui/lab/TabPanel"; +import OrderCard from "../../AtomicComponents/Cards/OrderDetailsCard"; + +export default function MyOrders() { + const [value, setValue] = React.useState("1"); + + const handleChange = (event, newValue) => { + setValue(newValue); + }; + + // Dummy data for orders + const orders = [ + { + id: 1, + status: "Awaiting delivery", + itemName: "Build name 1", + totalAmount: "LKR 250,000.00", + orderDate: "Nov 12, 2024", + orderId: "1109M8B2Y7A0Z3_O6W", + type: "build", + imageUrl: "https://via.placeholder.com/100", + }, + { + id: 2, + status: "Delivered", + itemName: "Item name 2", + totalAmount: "LKR 150,000.00", + orderDate: "Nov 10, 2024", + orderId: "1109M8B2Y7A0Z3_O6X", + type: "component", + imageUrl: "https://via.placeholder.com/100", + }, + { + id: 3, + status: "Awaiting delivery", + itemName: "Build name 3", + totalAmount: "LKR 350,000.00", + orderDate: "Nov 15, 2024", + orderId: "1109M8B2Y7A0Z3_O6Y", + type: "build", + imageUrl: "https://via.placeholder.com/100", + }, + ]; + + const filteredOrders = orders.filter((order) => { + if (value === "1") return true; + if (value === "2") return order.type === "build"; + if (value === "3") return order.type === "component"; + return false; + }); + + return ( +
+
+
+ +
+ +
+ + +
+ + + +

Your Orders

+ + + + + + + + + + + {filteredOrders.map((order) => ( + + ))} + + + {filteredOrders.map((order) => ( + + ))} + + + {filteredOrders.map((order) => ( + + ))} + + +
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/OrderDetailsContent.jsx b/client/src/UserdashboardFeature/pages/OrderDetailsContent.jsx new file mode 100644 index 0000000..a53fdb4 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/OrderDetailsContent.jsx @@ -0,0 +1,33 @@ +// import React, { useEffect, useState } from "react"; +// import OrderCard from "../../AtomicComponents/Cards/OrderCard"; + +// export default function CustomBuildsContent() { +// const [orders, setOrders] = useState([]); + +// useEffect(() => { +// // Replace with your actual API endpoint +// fetch('https://api.example.com/orders') +// .then(response => response.json()) +// .then(data => setOrders(data)) +// .catch(error => console.error('Error fetching data:', error)); +// }, []); + +// if (orders.length === 0) { +// return
Loading...
; +// } + +// return ( +//
+// {orders.map((order, index) => ( +// +// ))} +//
+// ); +// } diff --git a/client/src/UserdashboardFeature/pages/OrderHistory.jsx b/client/src/UserdashboardFeature/pages/OrderHistory.jsx new file mode 100644 index 0000000..1b32ecb --- /dev/null +++ b/client/src/UserdashboardFeature/pages/OrderHistory.jsx @@ -0,0 +1,39 @@ +import React, { useState } from "react"; +import SideNav from "../SideNav"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import { Box } from "@mui/material"; + +export default function OrderHistory() { + return ( +
+
+
+ +
+ +
+ + +
+ + + +

zTeshijfbj

+
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/RMAsupport.jsx b/client/src/UserdashboardFeature/pages/RMAsupport.jsx new file mode 100644 index 0000000..01d6293 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/RMAsupport.jsx @@ -0,0 +1,250 @@ +import React, { useState, useEffect } from "react"; +import axios from "axios"; +import SideNav from "../SideNav"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import { Box, Divider, Paper, Typography, Button } from "@mui/material"; +import { InputField } from "../../AtomicComponents/Inputs/Input"; +import { OutlinedButton } from "../../AtomicComponents/Buttons/Buttons"; + +export default function RMAsupport() { + const [formData, setFormData] = useState({ + subject: "", + orderId: "", + reason: "", + message: "", + userId: "67bb2ef04c2464b97ea7f9b4", // Replace with logged-in user ID + }); + + const [rmaRequests, setRmaRequests] = useState([]); + + // Handle form input changes + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + // Submit RMA request + const handleSubmit = async () => { + try { + const response = await axios.post( + "http://localhost:8000/api/rma", + formData + ); + alert("RMA request submitted successfully!"); + fetchRMARequests(); // Refresh RMA requests after submission + } catch (error) { + console.error("Error submitting RMA:", error); + alert("Failed to submit RMA request."); + } + }; + + // Fetch RMA requests for the user + const fetchRMARequests = async () => { + try { + const response = await axios.get( + `http://localhost:8000/api/rma/user/${formData.userId}` + ); + setRmaRequests(response.data); + } catch (error) { + console.error("Error fetching RMAs:", error); + } + }; + + // Fetch RMA requests on component mount + useEffect(() => { + fetchRMARequests(); + }, []); + + return ( +
+
+
+ +
+ +
+ + +
+ + + +

+ Support + Returns +

+ + +
+ + + +
+
+ +
+ +
+ +
+ +
+ + + {/* + + */} +
+
+

+ Active RMA Requests +

+ + + {rmaRequests.length === 0 ? ( + + No active RMA requests. + + ) : ( + rmaRequests.map((rma) => ( + +
+ + {rma.subject} + + + {rma.message} + +
+
+ + Date:{" "} + {new Date(rma.createdAt).toLocaleDateString()} + + + +
+
+ )) + )} +
+
+
+
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/SavedBuilds.jsx b/client/src/UserdashboardFeature/pages/SavedBuilds.jsx new file mode 100644 index 0000000..6aa5f1c --- /dev/null +++ b/client/src/UserdashboardFeature/pages/SavedBuilds.jsx @@ -0,0 +1,77 @@ +import React, { useState } from "react"; +import SideNav from "../SideNav"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import CustomBuildsContent from "./CustomBuildsContent"; +import PublishedBuildsContent from "../PublishedBuildsContent"; +import { Box } from "@mui/material"; +import Tab from "@mui/material/Tab"; +import TabContext from "@mui/lab/TabContext"; +import TabList from "@mui/lab/TabList"; +import TabPanel from "@mui/lab/TabPanel"; +import BuildIcon from "@mui/icons-material/Build"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; + +export default function SavedBuilds() { + const [value, setValue] = React.useState("1"); + + const handleChange = (event, newValue) => { + setValue(newValue); + }; + return ( +
+
+
+ +
+ +
+ + +
+ + + +

Your Builds

+ + + + + } + label="Custom Builds" + iconPosition="start" + value="1" + /> + } + iconPosition="start" + label="Published Builds" + value="2" + /> + + + + + + + + + +
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/Settings.jsx b/client/src/UserdashboardFeature/pages/Settings.jsx new file mode 100644 index 0000000..0c0dfc0 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/Settings.jsx @@ -0,0 +1,39 @@ +import React, { useState } from "react"; +import SideNav from "../SideNav"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import { Box } from "@mui/material"; + +export default function Settings() { + return ( +
+
+
+ +
+ +
+ + +
+ + + +

zTeshijfbj

+
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/pages/UserProfile.jsx b/client/src/UserdashboardFeature/pages/UserProfile.jsx new file mode 100644 index 0000000..e77a439 --- /dev/null +++ b/client/src/UserdashboardFeature/pages/UserProfile.jsx @@ -0,0 +1,226 @@ +import React, { useState, useEffect } from "react"; +import { useSelector, useDispatch } from "react-redux"; +import { Box } from "@mui/system"; +import SideNav from "../SideNav"; +import { Divider, Paper, Button } from "@mui/material"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { InputField } from "../../AtomicComponents/Inputs/Input"; +import { OutlinedButton } from "../../AtomicComponents/Buttons/Buttons"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import axios from "axios"; +import { toast } from "sonner"; +import { setAuthUser } from "../../Store/authSlice"; + +export default function UserProfile() { + const dispatch = useDispatch(); + const user = useSelector((state) => state.auth.user); + const [isEnabled, SetIsEnabled] = useState(false); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + name: "", + email: "", + firstName: "", + lastName: "", + address: "", + }); + + useEffect(() => { + if (user) { + setFormData({ + name: user.name || "", + email: user.email || "", + firstName: user.firstName || "", + lastName: user.lastName || "", + address: user.address || "", + }); + } + }, [user]); + + useEffect(() => { + const fetchUserProfile = async () => { + try { + const response = await axios.get("http://localhost:8000/api/v1/users", { + headers: { + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + }); + dispatch(setAuthUser(response.data)); + setFormData(response.data); + } catch (error) { + console.error("Error fetching profile:", error); + toast.error("Failed to load profile"); + } + }; + fetchUserProfile(); + }, [dispatch]); + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + + try { + const response = await axios.post( + "http://localhost:8000/api/v1/users/update-profile", + formData, + { + headers: { + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + } + ); + dispatch(setAuthUser(response.data)); + toast.success("Profile updated successfully"); + } catch (error) { + console.error("Update error:", error); + toast.error("Failed to update profile"); + } finally { + setLoading(false); + } + }; + const handleToggle = () => { + SetIsEnabled(!isEnabled); + }; + + return ( +
+
+
+ +
+ +
+ + +
+ + + +

Profile

+ + + +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ +

+ Two Factor Authentication(2FA) +

+

+ Status: {isEnabled ? "Enabled" : "Disabled"} +

+ +
+
+ + +

+ Change password +

+ +
+
+
+
+
+
+
+
+
+ ); +} diff --git a/client/src/UserdashboardFeature/testColor.jsx b/client/src/UserdashboardFeature/testColor.jsx new file mode 100644 index 0000000..3c70014 --- /dev/null +++ b/client/src/UserdashboardFeature/testColor.jsx @@ -0,0 +1,98 @@ +import * as React from "react"; +import PropTypes from "prop-types"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { createTheme } from "@mui/material/styles"; +import DashboardIcon from "@mui/icons-material/Dashboard"; +import ShoppingCartIcon from "@mui/icons-material/ShoppingCart"; +import { AppProvider } from "@toolpad/core/AppProvider"; +import { DashboardLayout } from "@toolpad/core/DashboardLayout"; +import { useDemoRouter } from "@toolpad/core/internal"; + +const NAVIGATION = [ + { + segment: "dashboard", + title: "Dashboard", + icon: , + }, + { + segment: "orders", + title: "Orders", + icon: , + }, +]; + +const demoTheme = createTheme({ + cssVariables: { + colorSchemeSelector: "data-toolpad-color-scheme", + }, + colorSchemes: { light: true, dark: true }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 600, + lg: 1200, + xl: 1536, + }, + }, +}); + +function DemoPageContent({ pathname }) { + return ( + + Dashboard content for {pathname} + + ); +} + +DemoPageContent.propTypes = { + pathname: PropTypes.string.isRequired, +}; + +function DashboardLayoutBranding(props) { + const { window } = props; + + const router = useDemoRouter("/dashboard"); + + // Remove this const when copying and pasting into your project. + const demoWindow = window !== undefined ? window() : undefined; + + return ( + // preview-start + , + title: "MUI", + homeUrl: "/toolpad/core/introduction", + }} + router={router} + theme={demoTheme} + window={demoWindow} + > + + + + + // preview-end + ); +} + +DashboardLayoutBranding.propTypes = { + /** + * Injected by the documentation to work in an iframe. + * Remove this when copying and pasting into your project. + */ + window: PropTypes.func, +}; + +export default DashboardLayoutBranding; diff --git a/client/src/assets/PC.webp b/client/src/assets/PC.webp new file mode 100644 index 0000000..38a119b Binary files /dev/null and b/client/src/assets/PC.webp differ diff --git a/client/src/assets/Sample.png b/client/src/assets/Sample.png new file mode 100644 index 0000000..e2b5e53 Binary files /dev/null and b/client/src/assets/Sample.png differ diff --git a/client/src/assets/images/ForCustomBuild/advanced-mode.png b/client/src/assets/images/ForCustomBuild/advanced-mode.png new file mode 100644 index 0000000..865651f Binary files /dev/null and b/client/src/assets/images/ForCustomBuild/advanced-mode.png differ diff --git a/client/src/assets/images/ForCustomBuild/easy-mode.png b/client/src/assets/images/ForCustomBuild/easy-mode.png new file mode 100644 index 0000000..d3c8040 Binary files /dev/null and b/client/src/assets/images/ForCustomBuild/easy-mode.png differ diff --git a/client/src/assets/images/Logos/1.png b/client/src/assets/images/Logos/1.png new file mode 100644 index 0000000..7b500f9 Binary files /dev/null and b/client/src/assets/images/Logos/1.png differ diff --git a/client/src/assets/images/Logos/2.png b/client/src/assets/images/Logos/2.png new file mode 100644 index 0000000..4cb76d8 Binary files /dev/null and b/client/src/assets/images/Logos/2.png differ diff --git a/client/src/assets/images/Logos/3.png b/client/src/assets/images/Logos/3.png new file mode 100644 index 0000000..79c9ad3 Binary files /dev/null and b/client/src/assets/images/Logos/3.png differ diff --git a/client/src/assets/images/Logos/4.png b/client/src/assets/images/Logos/4.png new file mode 100644 index 0000000..385846d Binary files /dev/null and b/client/src/assets/images/Logos/4.png differ diff --git a/client/src/assets/images/Logos/logo-black.png b/client/src/assets/images/Logos/logo-black.png new file mode 100644 index 0000000..8c30d91 Binary files /dev/null and b/client/src/assets/images/Logos/logo-black.png differ diff --git a/client/src/assets/images/Logos/logo-gray.png b/client/src/assets/images/Logos/logo-gray.png new file mode 100644 index 0000000..dbe662e Binary files /dev/null and b/client/src/assets/images/Logos/logo-gray.png differ diff --git a/client/src/assets/images/Logos/logo-userfooterblue.png b/client/src/assets/images/Logos/logo-userfooterblue.png new file mode 100644 index 0000000..ef3fe7a Binary files /dev/null and b/client/src/assets/images/Logos/logo-userfooterblue.png differ diff --git a/client/src/assets/images/Logos/logo-white.png b/client/src/assets/images/Logos/logo-white.png new file mode 100644 index 0000000..7bdc57c Binary files /dev/null and b/client/src/assets/images/Logos/logo-white.png differ diff --git a/client/src/assets/images/Logos/logo-white1.png b/client/src/assets/images/Logos/logo-white1.png new file mode 100644 index 0000000..3a8fca5 Binary files /dev/null and b/client/src/assets/images/Logos/logo-white1.png differ diff --git a/client/src/assets/images/Logos/logo-white2.png b/client/src/assets/images/Logos/logo-white2.png new file mode 100644 index 0000000..2b51ab3 Binary files /dev/null and b/client/src/assets/images/Logos/logo-white2.png differ diff --git a/client/src/assets/images/Logos/logo-white_0.png b/client/src/assets/images/Logos/logo-white_0.png new file mode 100644 index 0000000..6ff9765 Binary files /dev/null and b/client/src/assets/images/Logos/logo-white_0.png differ diff --git a/client/src/assets/logo.png b/client/src/assets/logo.png new file mode 100644 index 0000000..b6a473c Binary files /dev/null and b/client/src/assets/logo.png differ diff --git a/client/src/components/ItemCard.jsx b/client/src/components/ItemCard.jsx new file mode 100644 index 0000000..3c195d6 --- /dev/null +++ b/client/src/components/ItemCard.jsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; // ✅ FIXED +import { useDispatch } from 'react-redux'; +import { addToCart } from '../../src/redux/cartSlice'; + +const ItemCard = ({ product }) => { + const dispatch = useDispatch(); + + const handleAddToCart = (e) => { + e.stopPropagation(); // ✅ Prevent Link click + e.preventDefault(); // ✅ Prevent navigation + dispatch(addToCart(product)); + alert(`${product.name} added to cart`); + }; + + return ( +
+ + {/* Wrap only navigable content inside Link */} + + + {/* Stock availability label */} +
+ {product.quantity > 0 ? "In Stock" : "Out of Stock"} +
+ + {/* Image Section */} +
+ {product.name} +
+ + {/* Item Name Section */} +
+

+ {product.name} +

+
+ + {/* Price Section */} +

+ ${product.price} +

+ + + {/* Add to Cart Button OUTSIDE the Link */} +
+ +
+
+ ); +}; + +export default ItemCard; diff --git a/client/src/components/Layout/UserLayout.jsx b/client/src/components/Layout/UserLayout.jsx new file mode 100644 index 0000000..48d323b --- /dev/null +++ b/client/src/components/Layout/UserLayout.jsx @@ -0,0 +1,20 @@ +import React from 'react' +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' +import Footer from '../../MoleculesComponents/User_navbar_and_footer/Footer' + +export default function UserLayout() { + return ( +
+ + + + {/* Content */} + +
+ + + + +
+ ) +} diff --git a/client/src/components/contents/cards/Actioncard.jsx b/client/src/components/contents/cards/Actioncard.jsx new file mode 100644 index 0000000..af6f2ff --- /dev/null +++ b/client/src/components/contents/cards/Actioncard.jsx @@ -0,0 +1,20 @@ +import { Card, CardActions, CardContent, Button, Typography } from "@mui/material"; + +export default function Actioncard({ title = "Action Card", description = "Click below for details", buttonText = "Learn More", onClick }) { + return ( + + + {title} + + {description} + + + + + + + ); +} + +// how to use: +// console.log("Button Clicked")} /> diff --git a/client/src/components/contents/cards/Basiccard.jsx b/client/src/components/contents/cards/Basiccard.jsx new file mode 100644 index 0000000..4601360 --- /dev/null +++ b/client/src/components/contents/cards/Basiccard.jsx @@ -0,0 +1,17 @@ +import { Card, CardContent, Typography } from "@mui/material"; + +export default function Basiccard({ title = "Card Title", description = "Card description..." }) { + return ( + + + {title} + + {description} + + + + ); +} + +// how to use: +// diff --git a/client/src/components/contents/cards/Loadingskeleton.jsx b/client/src/components/contents/cards/Loadingskeleton.jsx new file mode 100644 index 0000000..b1fc8d9 --- /dev/null +++ b/client/src/components/contents/cards/Loadingskeleton.jsx @@ -0,0 +1,21 @@ +import { Card, CardContent, Skeleton } from "@mui/material"; + +export default function LoadingSkeleton() { + return ( + + {/* Simulated Image Placeholder */} + + + + {/* Simulated Title Placeholder */} + + + {/* Simulated Description Placeholder */} + + + + ); +} + +// Use: +// diff --git a/client/src/components/contents/cards/Mediacard.jsx b/client/src/components/contents/cards/Mediacard.jsx new file mode 100644 index 0000000..d9247a2 --- /dev/null +++ b/client/src/components/contents/cards/Mediacard.jsx @@ -0,0 +1,19 @@ +import { Card, CardContent, CardMedia, Typography } from "@mui/material"; + +export default function MediaCard({ image, title = "Media Card", description = "Media description..." }) { + return ( + + + + {title} + + {description} + + + + ); +} + +// Usage: +// + diff --git a/client/src/components/contents/cards/Usercard.jsx b/client/src/components/contents/cards/Usercard.jsx new file mode 100644 index 0000000..2e84a46 --- /dev/null +++ b/client/src/components/contents/cards/Usercard.jsx @@ -0,0 +1,19 @@ +import React from "react"; +import { Card, CardContent, Avatar, Typography } from "@mui/material"; + +export default function Usercard({ name='lasitha', email='lasitha@gmail.com', src='./logo.png' }) { + return ( + + + + {name} + {email} + + + ); +} + + + +//how to useee +// diff --git a/client/src/components/contents/cards/mediacards/Itemcard.jsx b/client/src/components/contents/cards/mediacards/Itemcard.jsx new file mode 100644 index 0000000..05c8ffc --- /dev/null +++ b/client/src/components/contents/cards/mediacards/Itemcard.jsx @@ -0,0 +1,61 @@ + +import React from 'react' +import { Link } from 'react-router-dom' + + + + + + + +export default function Itemcard({ src="/graph1.png" , stock="In Stock" , itemname = "ASUS ROG Strix RTX 4080 SUPER 16GB GDDR6X", price = "610,000 LKR" ,link='/itempage'}) { + return( +
+ + {/* Stock availability label */} +
+ {stock} +
+ + {/* Image Section */} +
+ {itemname} +
+ + {/* Item Name Section */} +
+

+ {itemname} +

+
+ + {/* Price Section */} +

{price}

+ + {/* Add to Cart Button */} + + + + +
+ +
+ + +
+ + ); +} + + + //how to useee-- + //given prop details are defaults...if you want to change.here is the way --> + + + + + // \ No newline at end of file diff --git a/client/src/components/contents/cards/mediacards/Itemcardsforpc.jsx b/client/src/components/contents/cards/mediacards/Itemcardsforpc.jsx new file mode 100644 index 0000000..3a1f534 --- /dev/null +++ b/client/src/components/contents/cards/mediacards/Itemcardsforpc.jsx @@ -0,0 +1,63 @@ + +export default function Itemcardforpc({ src="/graph1.png" , stock="In Stock" , itemname = "Player 1:Intel ARC Edition", price = "710,000 LKR" }) { + return ( + + +
+ {/* full border area up */} + + + {/* stock availability area */} + +
+ {stock} +
+ + + + {/* image area */} + +
+ {itemname}/ +
+ + + + + {/* name area */} + +
+

+

{itemname}

+

+
+ + + + + + {/* price area */} +

{price}

+ + + + {/* add to cart button area -- will replace with atomic button */} +
+ +
+ + +
+ ); + } + + + + + //how to useee-- + //given prop details are defaults...if you want to change.here is the way --> + + + // \ No newline at end of file diff --git a/client/src/components/contents/icons and images/Imageplaceholder.jsx b/client/src/components/contents/icons and images/Imageplaceholder.jsx new file mode 100644 index 0000000..bdb57ff --- /dev/null +++ b/client/src/components/contents/icons and images/Imageplaceholder.jsx @@ -0,0 +1,12 @@ +import ImageNotSupportedIcon from '@mui/icons-material/ImageNotSupported'; + +export default function Imageplaceholder({ bgColor = "#e0e0e0", size = "large" }) { + return ( +
+ +
+ ); +} + +// how to usssseee: +// diff --git a/client/src/components/contents/icons and images/Lazyloadingwrapper.jsx b/client/src/components/contents/icons and images/Lazyloadingwrapper.jsx new file mode 100644 index 0000000..ffbd1fc --- /dev/null +++ b/client/src/components/contents/icons and images/Lazyloadingwrapper.jsx @@ -0,0 +1,26 @@ +import { useState, useEffect } from "react"; +import { Skeleton } from "@mui/material"; + +export default function Lazyloadingwrapper({ src, alt = "Image", width = "100%", height = "200px", skeletonColor = "#ccc" }) { + const [loaded, setLoaded] = useState(false); + + useEffect(() => { + const img = new Image(); + img.src = src; + img.onload = () => setLoaded(true); + }, [src]); + + return ( +
+ {!loaded && } + {alt} +
+ ); +} + +// how to ussssssseee: +// diff --git a/client/src/components/contents/icons and images/icons/Deleteicon.jsx b/client/src/components/contents/icons and images/icons/Deleteicon.jsx new file mode 100644 index 0000000..701c0d9 --- /dev/null +++ b/client/src/components/contents/icons and images/icons/Deleteicon.jsx @@ -0,0 +1,10 @@ +import DeleteIcon from '@mui/icons-material/Delete'; + +export default function Deleteicon({ deleteColor = "primary", size = "large" }) +{ + return ( +
+ +
+ ); +} diff --git a/client/src/components/contents/icons and images/icons/Iconset.jsx b/client/src/components/contents/icons and images/icons/Iconset.jsx new file mode 100644 index 0000000..e7cbe61 --- /dev/null +++ b/client/src/components/contents/icons and images/icons/Iconset.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import EditIcon from "@mui/icons-material/Edit"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; +import SearchIcon from "@mui/icons-material/Search"; +import VisibilityIcon from "@mui/icons-material/Visibility"; +import DashboardIcon from "@mui/icons-material/Dashboard"; +import SettingsIcon from "@mui/icons-material/Settings"; +import ShoppingBagIcon from "@mui/icons-material/ShoppingBag"; +import ReceiptIcon from "@mui/icons-material/Receipt"; +import GroupIcon from "@mui/icons-material/Group"; +import FeedbackIcon from "@mui/icons-material/Feedback"; +import PhoneIcon from "@mui/icons-material/Phone"; +import EmailIcon from "@mui/icons-material/Email"; +import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; +import PlaceIcon from "@mui/icons-material/Place"; +import NotificationsIcon from "@mui/icons-material/Notifications"; +import DarkModeIcon from "@mui/icons-material/DarkMode"; +import VpnKeyIcon from "@mui/icons-material/VpnKey"; +import CreateIcon from "@mui/icons-material/Create"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import DownloadIcon from "@mui/icons-material/Download"; +import MessageIcon from "@mui/icons-material/Message"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; +import MonetizationOnIcon from "@mui/icons-material/MonetizationOn"; +import HourglassEmptyIcon from "@mui/icons-material/HourglassEmpty"; + +export default function Iconset({ type='notification', fontSize='30px', color = "primary" }) { + const renderIcon = () => { + switch (type) { + case 'edit': return ; + case 'more': return ; + case 'delete': return ; + case 'add': return ; + case 'search': return ; + case 'view': return ; + case 'dashboard': return ; + case 'settings': return ; + case 'product': return ; + case 'order': return ; + case 'user-manage': return ; + case 'feedback-manage': return ; + case 'invoice': return ; + case 'call': return ; + case 'email': return ; + case 'calendar': return ; + case 'location': return ; + case 'notification': return ; + case 'darkmode': return ; + case 'key': return ; + case 'pen': return ; + case 'heart': return ; + case 'download': return ; + case 'message': return ; + case 'signout': return ; + case 'money': return ; + case 'pending': return ; + default: return null; + } + }; + return {renderIcon()}; +} + + + +//font size should be in pixels diff --git a/client/src/components/contents/icons and images/icons/Personicon.jsx b/client/src/components/contents/icons and images/icons/Personicon.jsx new file mode 100644 index 0000000..a4227bf --- /dev/null +++ b/client/src/components/contents/icons and images/icons/Personicon.jsx @@ -0,0 +1,11 @@ +import PersonIcon from '@mui/icons-material/Person'; + + +export default function Personicon({ userColor = "action", size = "large" ,}) +{ + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/client/src/components/contents/icons and images/icons/Searchicon.jsx b/client/src/components/contents/icons and images/icons/Searchicon.jsx new file mode 100644 index 0000000..c4b554d --- /dev/null +++ b/client/src/components/contents/icons and images/icons/Searchicon.jsx @@ -0,0 +1,11 @@ +import SearchIcon from '@mui/icons-material/Search'; + + +export default function Searchicon ({ searchColor = "secondary", size = "large" }) +{ + return ( +
+ +
+ ); + } \ No newline at end of file diff --git a/client/src/components/contents/icons and images/icons/Shoppingcarticon.jsx b/client/src/components/contents/icons and images/icons/Shoppingcarticon.jsx new file mode 100644 index 0000000..038c5dd --- /dev/null +++ b/client/src/components/contents/icons and images/icons/Shoppingcarticon.jsx @@ -0,0 +1,10 @@ +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; + +export default function ShoppingcartIcon({ cartColor = "primary", size = "large" }) +{ + return ( +
+ +
+ ); +} diff --git a/client/src/components/contents/icons and images/logos/Logo.jsx b/client/src/components/contents/icons and images/logos/Logo.jsx new file mode 100644 index 0000000..2fb82c8 --- /dev/null +++ b/client/src/components/contents/icons and images/logos/Logo.jsx @@ -0,0 +1,9 @@ +export default function Logo({ src = "/logo.png", alt = "Logo", width = "150px", height = "50px" }) { + return ( + {alt} + ); + } + + +// how to useeee: +// \ No newline at end of file diff --git a/client/src/index.css b/client/src/index.css index 6119ad9..bd6213e 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,68 +1,3 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/client/src/main.jsx b/client/src/main.jsx index b9a1a6d..95b6695 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -1,10 +1,137 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.jsx' - -createRoot(document.getElementById('root')).render( - - - , -) +import React from "react"; +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { Provider } from "react-redux"; +import store from "./Store/store.js"; // Import your Redux store +import "./index.css"; +import App from "./App.jsx"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { ThemeProvider } from "@mui/material/styles"; +import theme from "./AtomicComponents/theme.jsx"; +import { Toaster } from "sonner"; + +// Admin Components +import Dashboard from "./Admin/Dashboard.jsx"; +import AdminProfile from "./Admin/AdminProfile.jsx"; +import AdminSetting from "./Admin/AdminSetting.jsx"; +import Layout from "./Admin/Layout.jsx"; +import ManageProducts from "./Admin/ManageProducts.jsx"; +import CreateProducts from "./Admin/CreateProducts.jsx"; +import Usermanage from "./Admin/Usermanage.jsx"; +import Complaints from "./Admin/Complaints.jsx"; +import RMA from "./Admin/RMA.jsx"; +import Review from "./Admin/Review.jsx"; +import InvoiceList from "./Admin/InvoiceList.jsx"; +import InvoiceCreate from "./Admin/InvoiceCreate.jsx"; + +// Login Components +import Signup from "./Login/Signup.jsx"; +import Login from "./Login/Login.jsx"; +import Verify from "./Login/Verify.jsx"; +import ResetPassword from "./Login/Resetpassword.jsx"; +import ForgetPassword from "./Login/Forgetpassword.jsx"; + +// User Components +import ComplaintSubmit from "./User/ComplaintSubmit.jsx"; +import UserComplaints from "./User/UserComplaints.jsx"; +import UserProfile from "./UserdashboardFeature/pages/UserProfile.jsx"; +import RMAsupport from "./UserdashboardFeature/pages/RMAsupport.jsx"; +import MyOrders from "./UserdashboardFeature/pages/MyOrders.jsx"; +import OrderHistory from "./UserdashboardFeature/pages/OrderHistory.jsx"; +import SavedBuilds from "./UserdashboardFeature/pages/SavedBuilds.jsx"; +import Settings from "./UserdashboardFeature/pages/Settings.jsx"; + +// Other Pages +import Home from "./pages/Home/Home.jsx"; +import About from "./pages/About_page/About.jsx"; +import LoginPage from "./pages/Login_page/Login_page.jsx"; +import CartPage from "./pages/Shopping_cart/CartPage.jsx"; +import PaymentGateway from "./pages/Shopping_cart/PaymentGateway.jsx"; +import ProductCategoryPage from "./pages/Producat_category/Productcategorypage.jsx"; +import ItemPage from "./pages/Single_Item/Itempage.jsx"; +import SearchResults from "./pages/Searchbar/SearchResults.jsx"; +import LaptopCategoryPage from "./pages/Laptop_category/Laptopcategorypage.jsx"; +import Testing from "./pages/Testing.jsx"; +import CreateGames from "./Admin/CreateGames.jsx"; // Import CreateGames +import ManageGames from "./Admin/ManageGames.jsx"; // Placeholder for ManageGames +import SelectGameAndBudgetpage from "./pages/SelectGameAndBudgetPage/SelectGameAndBudgetPage.jsx" +export const backendUrl = import.meta.env.VITE_BACKEND_URL; + +const root = document.getElementById("root"); + +createRoot(root).render( + + + + + + + {/* Public Routes */} + + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } + /> + } /> + } /> + } /> + + {/* Authentication Routes */} + } /> + } /> + } /> + } /> + } /> + + {/* User Routes */} + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + {/* Admin Routes */} + + } /> + } /> + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + + } /> + } + /> + } /> + } /> + + + + + +); diff --git a/client/src/pages/About.jsx b/client/src/pages/About.jsx new file mode 100644 index 0000000..cc1846a --- /dev/null +++ b/client/src/pages/About.jsx @@ -0,0 +1,17 @@ +import React from 'react' +import Navbar from '../components/Navbar' + +export default function About() { + return ( +
+ + + + + +

this is about

+ + +
+ ) +} diff --git a/client/src/pages/About_page/About.jsx b/client/src/pages/About_page/About.jsx new file mode 100644 index 0000000..836374a --- /dev/null +++ b/client/src/pages/About_page/About.jsx @@ -0,0 +1,17 @@ +import React from 'react' +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' + +export default function About() { + return ( +
+ + + + + +

this is About

+ + +
+ ) +} diff --git a/client/src/pages/Category_page.jsx b/client/src/pages/Category_page.jsx new file mode 100644 index 0000000..5031fc2 --- /dev/null +++ b/client/src/pages/Category_page.jsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function Category_page() { + return ( +

This is Category_page

+ ) +} diff --git a/client/src/pages/Home.jsx b/client/src/pages/Home.jsx new file mode 100644 index 0000000..20be721 --- /dev/null +++ b/client/src/pages/Home.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import Navbar from '../components/Navbar' + +export default function Home() { + return ( +
+ + +

this is home

+ + + +
+ ) +} diff --git a/client/src/pages/Home/Home.jsx b/client/src/pages/Home/Home.jsx new file mode 100644 index 0000000..f947c06 --- /dev/null +++ b/client/src/pages/Home/Home.jsx @@ -0,0 +1,22 @@ +import React from 'react' + +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' +import Footer from '../../MoleculesComponents/User_navbar_and_footer/Footer' + +import Home_part1 from './Home_part1/Home_part1' +import Home_part4 from './Home_part4/Home_part4' +import Home_part2 from './Home_part2/Home_part2' + +export default function Home() { + return ( +
+ + + + + +
+ +
+ ) +} diff --git a/client/src/pages/Home/Home_part1.jsx b/client/src/pages/Home/Home_part1.jsx new file mode 100644 index 0000000..cfbc007 --- /dev/null +++ b/client/src/pages/Home/Home_part1.jsx @@ -0,0 +1,51 @@ +import Button from "@mui/material/Button"; + +export default function Home_part1() { + return ( +
+ + + {/*image */} + Gaming Setup + + + + + {/*content */} +
+ +

+ Desk Deals Done Right. +

+ + +

+ Save big on gaming gear bundles and deck out your desk. +

+ + + + + + +
+ + +
+ ); +} + + + +//i divided home to 5 parts.5components.this is first component +//for change image pass the prop and add propcall to image src//<--for future work \ No newline at end of file diff --git a/client/src/pages/Home/Home_part1/Home_part1.jsx b/client/src/pages/Home/Home_part1/Home_part1.jsx new file mode 100644 index 0000000..cfbc007 --- /dev/null +++ b/client/src/pages/Home/Home_part1/Home_part1.jsx @@ -0,0 +1,51 @@ +import Button from "@mui/material/Button"; + +export default function Home_part1() { + return ( +
+ + + {/*image */} + Gaming Setup + + + + + {/*content */} +
+ +

+ Desk Deals Done Right. +

+ + +

+ Save big on gaming gear bundles and deck out your desk. +

+ + + + + + +
+ + +
+ ); +} + + + +//i divided home to 5 parts.5components.this is first component +//for change image pass the prop and add propcall to image src//<--for future work \ No newline at end of file diff --git a/client/src/pages/Home/Home_part2/Home_part2.jsx b/client/src/pages/Home/Home_part2/Home_part2.jsx new file mode 100644 index 0000000..20c392b --- /dev/null +++ b/client/src/pages/Home/Home_part2/Home_part2.jsx @@ -0,0 +1,42 @@ +//http://localhost:5000/api/products + + +import { useEffect, useState } from "react"; +import axios from "axios"; +import PCcardhome from "./Pccardhome"; + +export default function Home_part2() { + const [pcs, setPcs] = useState([]); + + useEffect(() => { + const fetchPCs = async () => { + try { + const response = await axios.get('http://localhost:8000/api/product/filter?'); // Axios fetch + setPcs(response.data.slice(0, 8)); // Select only the first 8 items + } catch (error) { + console.error("Error fetching products:", error); + } + }; + + fetchPCs(); + }, []); + + return ( +
+ {/* Title */} +

Prebuilt Gaming PCs

+

+ We use the latest generation performance components and configurations to get you gaming fast. +

+ + {/* Cards with mapping*/} +
+ {pcs.map((pc) => ( +
+ +
+ ))} +
+
+ ); +} diff --git a/client/src/pages/Home/Home_part2/Pccardhome.jsx b/client/src/pages/Home/Home_part2/Pccardhome.jsx new file mode 100644 index 0000000..7caf437 --- /dev/null +++ b/client/src/pages/Home/Home_part2/Pccardhome.jsx @@ -0,0 +1,40 @@ +import { useNavigate } from "react-router-dom"; +import Button from "@mui/material/Button"; + +export default function PCcardhome({ id,name, image, specs = "RTX 4060 Ti, Ryzen 7 5800X", price }) { + + const navigate = useNavigate(); + + const handleShopClick = () => { + navigate(`/itempage/${id}`); // Redirect to ItemPage + }; + + + + return ( +
+ {name} + +

{name}

+ +

{specs}

+ +

{price}

+ + +
+ ); +} diff --git a/client/src/pages/Home/Home_part4/Home_part4.jsx b/client/src/pages/Home/Home_part4/Home_part4.jsx new file mode 100644 index 0000000..ae9a09e --- /dev/null +++ b/client/src/pages/Home/Home_part4/Home_part4.jsx @@ -0,0 +1,37 @@ +////http://localhost:5000/api/products + + +import { useEffect, useState } from "react"; +import axios from "axios"; +import Reviewcardhome from "./Reviewcardhome"; + +export default function Home_part4() { + const [reviews, setReviews] = useState([]); + + useEffect(() => { + const fetchReviews = async () => { + try { + const response = await axios.get("http://localhost:8000/api/product/filter?"); // Fetch data from backend + setReviews(response.data.slice(0, 6)); // Show only 6 reviews + } catch (error) { + console.error("Error fetching reviews:", error); + } + }; + + fetchReviews(); + }, []); + + return ( +
+ {/* Section Title */} +

Customer Feedback

+ + {/* Reviews Grid */} +
+ {reviews.map((review) => ( + + ))} +
+
+ ); +} diff --git a/client/src/pages/Home/Home_part4/Reviewcardhome.jsx b/client/src/pages/Home/Home_part4/Reviewcardhome.jsx new file mode 100644 index 0000000..fb34845 --- /dev/null +++ b/client/src/pages/Home/Home_part4/Reviewcardhome.jsx @@ -0,0 +1,26 @@ +export default function Reviewcardhome({ review }) { + return ( +
+ {/* Reviewer Info */} +
+ {review.name} +

{review.name}

+
+ + {/* Star Rating --for future works */} + + {/* +
+ {Array.from({ length: 5 }).map((_, i) => ( + + ★ + + ))} +
*/} + + + {/* Review Comment */} +

{review.description}

+
+ ); +} diff --git a/client/src/pages/Laptop_category/Laptop/Laptopcategoryposter.jsx b/client/src/pages/Laptop_category/Laptop/Laptopcategoryposter.jsx new file mode 100644 index 0000000..4202cfc --- /dev/null +++ b/client/src/pages/Laptop_category/Laptop/Laptopcategoryposter.jsx @@ -0,0 +1,36 @@ +import React from "react"; + + +const Laptopcategoryposter = () => { + + + + + + +// switch case for category title and poster changing // + + + var image = "https://images.pexels.com/photos/303383/pexels-photo-303383.jpeg?cs=srgb&dl=pexels-veeterzy-303383.jpg&fm=jpg"; //category background image + + + + + + + + + return ( +
+
+

LAPTOPS

+
+ ); +}; + +export default Laptopcategoryposter; + + diff --git a/client/src/pages/Laptop_category/Laptop/Laptopfitering.jsx b/client/src/pages/Laptop_category/Laptop/Laptopfitering.jsx new file mode 100644 index 0000000..e92a44d --- /dev/null +++ b/client/src/pages/Laptop_category/Laptop/Laptopfitering.jsx @@ -0,0 +1,95 @@ +import { Checkbox, Slider, TextField, FormControlLabel } from "@mui/material"; +import StarIcon from "@mui/icons-material/Star"; + +export default function Laptopfiltering() { + return ( + + +
+ {/* RAM Size */} + + + + + +
+

Brands

+ + + {["32GB", "24GB", "16GB", "12GB", "8GB", "4GB"].map((size) => ( + } label={size} className="block" /> + ))} + + +
+ + + + + + + + + {/* Price Range */} +
+

Price Range

+ + + + + +
+ + - + +
+
+ + {/* Brands */} +
+

Brands

+ + + {["Mac", "Karts", "Baals", "Bukks", "Luasis"].map((brand) => ( + } label={brand} className="block" /> + ))} + + +
+ + + + + + {/* Other Filters */} +
+ } label="On Sale" className="block" /> + } label="In Stock" className="block" /> + } label="Featured" className="block" /> +
+ + + + + + {/* Ratings */} +
+

Ratings

+ {[5, 4, 3, 2, 1].map((stars) => ( + } + label={ +
+ {Array.from({ length: 5 }).map((_, i) => ( + + ))} +
+ } + className="block" + /> + ))} +
+
+ ); +} diff --git a/client/src/pages/Laptop_category/Laptop/Laptopgrid.jsx b/client/src/pages/Laptop_category/Laptop/Laptopgrid.jsx new file mode 100644 index 0000000..4b21cea --- /dev/null +++ b/client/src/pages/Laptop_category/Laptop/Laptopgrid.jsx @@ -0,0 +1,76 @@ +import React, { useEffect, useState } from 'react'; +import { Link } from "react-router-dom"; +import { useParams } from 'react-router-dom'; +import axios from "axios" +import Itemcard from '../../../components/ItemCard'; +import Navbar from '../../../MoleculesComponents/User_navbar_and_footer/Navbar'; +import Footer from '../../../MoleculesComponents/User_navbar_and_footer/Footer'; + + + + +export default function Laptopgrid() { + + + + const [laps, setLaps] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Fetch products by category + const fetchLaps = async () => { + try { + const response = await axios.get( + `http://localhost:5000/api/laptops/` + ); + setLaps(response.data); + setLoading(false); + } catch (error) { + console.error('Error fetching products:', error); + setLoading(false); + } + }; + + fetchLaps(); + }, []); + + if (loading) { + return
Loading...
; + } + + + return ( + + + +
+ + + + + + + + {/* if you want test remove ml and mt of below div.. */} + + +
+ {laps.map(lap => ( + + ))} +
+ + + + + + + +
+ + + ) +} + + + diff --git a/client/src/pages/Laptop_category/Laptopcategorypage.jsx b/client/src/pages/Laptop_category/Laptopcategorypage.jsx new file mode 100644 index 0000000..8fe958b --- /dev/null +++ b/client/src/pages/Laptop_category/Laptopcategorypage.jsx @@ -0,0 +1,28 @@ +import React from 'react' +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' +import Laptopgrid from './Laptop/Laptopgrid' +import Laptopfiltering from './Laptop/laptopfitering' +import Laptopcategoryposter from './Laptop/Laptopcategoryposter' + + +export default function Laptopcategorypage() { + return ( +
+ + + + + + +

All Laptops

+ + + + + + + + +
+ ) +} diff --git a/client/src/pages/Login_page.jsx b/client/src/pages/Login_page.jsx new file mode 100644 index 0000000..b7faf7c --- /dev/null +++ b/client/src/pages/Login_page.jsx @@ -0,0 +1,16 @@ +import React from 'react' +import Navbar from '../MoleculesComponents/User_navbar_and_footer/Navbar' + + + +export default function Login_page() { + return ( +
+ +

This is Login_page

+ + + +
+ ) +} diff --git a/client/src/pages/Login_page/Login_page.jsx b/client/src/pages/Login_page/Login_page.jsx new file mode 100644 index 0000000..0af930f --- /dev/null +++ b/client/src/pages/Login_page/Login_page.jsx @@ -0,0 +1,16 @@ +import React from 'react' +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' + + + +export default function Login_page() { + return ( +
+ +

This is Login_page

+ + + +
+ ) +} diff --git a/client/src/pages/Producat_category/Productcategorypage.jsx b/client/src/pages/Producat_category/Productcategorypage.jsx new file mode 100644 index 0000000..2d82af3 --- /dev/null +++ b/client/src/pages/Producat_category/Productcategorypage.jsx @@ -0,0 +1,29 @@ +import React from 'react' +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar' +import Filteringsystem from './Products/Filteringsystem' +import Product_item_grid from './Products/Product_item_grid' +import Categoryposter from './Products/Categoryposter' + + + +export default function Productcategorypage() { + return ( +
+ + + + + + +

All Products

+ + + + + + + + +
+ ) +} diff --git a/client/src/pages/Producat_category/Products/Categoryposter.jsx b/client/src/pages/Producat_category/Products/Categoryposter.jsx new file mode 100644 index 0000000..5337154 --- /dev/null +++ b/client/src/pages/Producat_category/Products/Categoryposter.jsx @@ -0,0 +1,104 @@ +import React from "react"; +import { useEffect, useState } from 'react'; +import { Link } from "react-router-dom"; +import { useParams } from 'react-router-dom'; +import axios from "axios" + +const Categoryposter = () => { + + + + const { categoryName } = useParams(); // Get the category name from the URL + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(true); + + + + // Fetch products by category + + useEffect(() => { + const fetchProducts = async () => { + try { + const response = await axios.get( + `http://localhost:8000/api/product/filter?attribute=type&value=${categoryName}` + ); + setProducts(response.data); + setLoading(false); + } catch (error) { + console.error('Error fetching products:', error); + setLoading(false); + } + }; + + fetchProducts(); + }, [categoryName]); + + if (loading) { + return
Loading...
; + } + + + + + + + +// switch case for category title and poster changing // + + + var title = ""; //category title + var image = ""; //category background image + + switch (categoryName) { + case "gpu": + title = "GRAPHIC CARDS"; + image ='../categorybg.jpg'; + break; + + case "ram": + title = "RAM CARDS"; + image ='../rambanner.jpg'; + + break; + + case "processor": + title = "PROCESSORS"; + image ='../processorbannernew.jpg'; + break; + + case "motherboard": + title = "MOTHERBOARDS"; + break; + + case "laptop": + title = "LAPTOPS"; + break; + + default: + break; + } + + + + + + + + + + + + return ( +
+
+

{title}

+
+ ); +}; + +export default Categoryposter; + + diff --git a/client/src/pages/Producat_category/Products/Filteringsystem.jsx b/client/src/pages/Producat_category/Products/Filteringsystem.jsx new file mode 100644 index 0000000..e76c9cf --- /dev/null +++ b/client/src/pages/Producat_category/Products/Filteringsystem.jsx @@ -0,0 +1,95 @@ +import { Checkbox, Slider, TextField, FormControlLabel } from "@mui/material"; +import StarIcon from "@mui/icons-material/Star"; + +export default function Filteringsystem() { + return ( + + +
+ {/* RAM Size */} + + + + + +
+

Brands

+ + + {["32GB", "24GB", "16GB", "12GB", "8GB", "4GB"].map((size) => ( + } label={size} className="block" /> + ))} + + +
+ + + + + + + + + {/* Price Range */} +
+

Price Range

+ + + + + +
+ + - + +
+
+ + {/* Brands */} +
+

Brands

+ + + {["Mac", "Karts", "Baals", "Bukks", "Luasis"].map((brand) => ( + } label={brand} className="block" /> + ))} + + +
+ + + + + + {/* Other Filters */} +
+ } label="On Sale" className="block" /> + } label="In Stock" className="block" /> + } label="Featured" className="block" /> +
+ + + + + + {/* Ratings */} +
+

Ratings

+ {[5, 4, 3, 2, 1].map((stars) => ( + } + label={ +
+ {Array.from({ length: 5 }).map((_, i) => ( + + ))} +
+ } + className="block" + /> + ))} +
+
+ ); +} diff --git a/client/src/pages/Producat_category/Products/Gridcard.jsx b/client/src/pages/Producat_category/Products/Gridcard.jsx new file mode 100644 index 0000000..acc8d71 --- /dev/null +++ b/client/src/pages/Producat_category/Products/Gridcard.jsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Gridcard = ({ product }) => { + return ( +
+ + {/* Navigate to Itempage with product ID */} + + {/* Stock availability label */} +
+ {product.stock > 0 ? "In Stock" : "Out of Stock"} +
+ + {/* Image Section */} +
+ {product.name} +
+ + {/* Item Name Section */} +
+

+ {product.name} +

+
+ + {/* Price Section */} +

+ ${product.price} +

+ + + + {/* Add to Cart Button */} +
+ +
+ +
+ ); +}; + +export default Gridcard; diff --git a/client/src/pages/Producat_category/Products/ProductDetails.jsx b/client/src/pages/Producat_category/Products/ProductDetails.jsx new file mode 100644 index 0000000..688ddde --- /dev/null +++ b/client/src/pages/Producat_category/Products/ProductDetails.jsx @@ -0,0 +1,44 @@ +import React from 'react' + +export default function ProductDetails() { + + const similarproducts = [ + + { + _id:1, + name:"product1", + price:100, + image: [{url:"#"}], + }, + { + _id:2, + name:"product2", + price:100, + image: [{url:"#"}], + }, + { + _id:3, + name:"product3", + price:100, + image: [{url:"#"}], + }, + { + _id:4, + name:"product4", + price:100, + image: [{url:"#"}], + }, + + ]; + + + + return ( +
ProductDetails
+ ) +} + + + + + diff --git a/client/src/pages/Producat_category/Products/Product_item_grid.jsx b/client/src/pages/Producat_category/Products/Product_item_grid.jsx new file mode 100644 index 0000000..2c3e23d --- /dev/null +++ b/client/src/pages/Producat_category/Products/Product_item_grid.jsx @@ -0,0 +1,77 @@ +import React, { useEffect, useState } from 'react'; +import { Link } from "react-router-dom"; +import { useParams } from 'react-router-dom'; +import axios from "axios" +import Itemcard from '../../../components/ItemCard'; + + + + +export default function Product_item_grid() { + + + + const { categoryName } = useParams(); // Get the category name from the URL + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Fetch products by category + const fetchProducts = async () => { + try { + const response = await axios.get( + `http://localhost:8000/api/product/filter?attribute=type&value=${categoryName}` + ); + console.log("product==================", response) + setProducts(response.data); + setLoading(false); + } catch (error) { + console.error('Error fetching products:', error); + setLoading(false); + } + }; + + fetchProducts(); + }, [categoryName]); + + if (loading) { + return
Loading...
; + } + + + return ( + + + +
+ + + + + + + + + {/* if you want test remove ml and mt of below div.. */} + +
+ {products.map(product => ( + + ))} +
+ + + + + + + + +
+ + + ) +} + + + diff --git a/client/src/pages/Producat_category/Products/SortOptions.jsx b/client/src/pages/Producat_category/Products/SortOptions.jsx new file mode 100644 index 0000000..73f811c --- /dev/null +++ b/client/src/pages/Producat_category/Products/SortOptions.jsx @@ -0,0 +1,7 @@ +import React from 'react' + +export default function SortOptions() { + return ( +
SortOptions
+ ) +} diff --git a/client/src/pages/Producat_category/components/Categoryposter.jsx b/client/src/pages/Producat_category/components/Categoryposter.jsx new file mode 100644 index 0000000..b7e7667 --- /dev/null +++ b/client/src/pages/Producat_category/components/Categoryposter.jsx @@ -0,0 +1,23 @@ +import React from "react"; + +const Categoryposter = ({ categoryName = 'GRAPHIC CARDS', imageSrc='./categorybg.jpg' }) => { + return ( +
+
+

{categoryName}

+
+ ); +}; + +export default Categoryposter; + + +//how to use +//default text is graphic card and default image is categorybg.jpg in public folder//default means there are no props called in your component.. + + +//if you want to pass props--> +// \ No newline at end of file diff --git a/client/src/pages/Producat_category/components/Filteringsystem.jsx b/client/src/pages/Producat_category/components/Filteringsystem.jsx new file mode 100644 index 0000000..e76c9cf --- /dev/null +++ b/client/src/pages/Producat_category/components/Filteringsystem.jsx @@ -0,0 +1,95 @@ +import { Checkbox, Slider, TextField, FormControlLabel } from "@mui/material"; +import StarIcon from "@mui/icons-material/Star"; + +export default function Filteringsystem() { + return ( + + +
+ {/* RAM Size */} + + + + + +
+

Brands

+ + + {["32GB", "24GB", "16GB", "12GB", "8GB", "4GB"].map((size) => ( + } label={size} className="block" /> + ))} + + +
+ + + + + + + + + {/* Price Range */} +
+

Price Range

+ + + + + +
+ + - + +
+
+ + {/* Brands */} +
+

Brands

+ + + {["Mac", "Karts", "Baals", "Bukks", "Luasis"].map((brand) => ( + } label={brand} className="block" /> + ))} + + +
+ + + + + + {/* Other Filters */} +
+ } label="On Sale" className="block" /> + } label="In Stock" className="block" /> + } label="Featured" className="block" /> +
+ + + + + + {/* Ratings */} +
+

Ratings

+ {[5, 4, 3, 2, 1].map((stars) => ( + } + label={ +
+ {Array.from({ length: 5 }).map((_, i) => ( + + ))} +
+ } + className="block" + /> + ))} +
+
+ ); +} diff --git a/client/src/pages/Producat_category/components/Product_item_grid.jsx b/client/src/pages/Producat_category/components/Product_item_grid.jsx new file mode 100644 index 0000000..d644e2a --- /dev/null +++ b/client/src/pages/Producat_category/components/Product_item_grid.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import Itemcard from '../../../components/contents/cards/mediacards/Itemcard'; + + + +export default function Product_item_grid() { + return ( +
+ + + +
+ + + {Array.from({ length: 9 }).map((_, index) => ( + + ))} +
+ + + +
+ + ); +} diff --git a/client/src/pages/Searchbar/SearchResults.jsx b/client/src/pages/Searchbar/SearchResults.jsx new file mode 100644 index 0000000..141e7ab --- /dev/null +++ b/client/src/pages/Searchbar/SearchResults.jsx @@ -0,0 +1,58 @@ +import React, { useEffect, useState } from "react"; +import { useLocation } from "react-router-dom"; +import axios from "axios"; +import ItemCard from "../../components/ItemCard" +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import Footer from "../../MoleculesComponents/User_navbar_and_footer/Footer"; + +export default function SearchResults() { + const location = useLocation(); + const query = new URLSearchParams(location.search).get("query"); + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(true); + + const [error, setError] = useState(null); + + useEffect(() => { + const fetchProducts = async () => { + try { + const response1 = await axios.get(`http://localhost:8000/api/product/search?query=${query}`); + setProducts(response1.data); + + + } catch (error) { + setError("Error fetching search results"); + } finally { + setLoading(false); + } + }; + + if (query) fetchProducts(); + }, [query]); + + if (loading) return

Loading results...

; + if (error) return

{error}

; + + return ( +
+ + +
+

+ +

+ Search results for: {query} +

+

+

+ +
+ {products.map((product) => ( + + ))} +
+
+
+
+ ); +} diff --git a/client/src/pages/SelectGameAndBudgetPage/SelectGameAndBudgetPage.jsx b/client/src/pages/SelectGameAndBudgetPage/SelectGameAndBudgetPage.jsx new file mode 100644 index 0000000..8a8a99d --- /dev/null +++ b/client/src/pages/SelectGameAndBudgetPage/SelectGameAndBudgetPage.jsx @@ -0,0 +1,109 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import SelectPcHeader from '../../AtomicComponents/ForCustomBuild/SelectPcHeader'; +import GameSelector from '../../AtomicComponents/ForCustomBuild/GameSelector'; +import BudgetSelector from '../../AtomicComponents/ForCustomBuild/BudgetSelector'; +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar'; +import Footer from '../../MoleculesComponents/User_navbar_and_footer/Footer'; +import PrebuiltPcPopup from '../../AtomicComponents/ForCustomBuild/PrebuiltPcPopup'; + +function SelectGameAndBudgetPage() { + const [budget, setBudget] = useState(800000); + const [selectedGames, setSelectedGames] = useState([]); + const [showPrebuiltPopup, setShowPrebuiltPopup] = useState(false); + const [prebuiltPcs, setPrebuiltPcs] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const handleBudgetChange = (newBudget) => { + setBudget(newBudget); + }; + + const handleGameSelect = (game) => { + if (!selectedGames.some((g) => g.id === game.id)) { + setSelectedGames([...selectedGames, game]); + } + }; + + const handleRemoveGame = (gameId) => { + setSelectedGames(selectedGames.filter((game) => game.id !== gameId)); + }; + + const handleApply = async () => { + if (selectedGames.length === 0) { + alert('Please select at least one game.'); + return; + } + + setLoading(true); + setError(null); + + try { + const highestGameScore = Math.max(...selectedGames.map((game) => game.scores.total)); + const response = await axios.get('http://localhost:8000/api/product/all'); + if (response.data.Success) { + const allProducts = response.data.data; + const prebuilds = allProducts.filter((product) => product.type === 'prebuild'); + setPrebuiltPcs(prebuilds); + setShowPrebuiltPopup(true); + } else { + setError('Failed to fetch prebuilt PCs'); + } + } catch (err) { + console.error('Error fetching prebuilt PCs:', err.message); + setError('Unable to connect to the server. Please try again later.'); + } finally { + setLoading(false); + } + }; + + const handleClosePopup = () => { + setShowPrebuiltPopup(false); + }; + + return ( +
+ +
+
+ +
+ +
+ +
+
+
+
+
+ {showPrebuiltPopup && ( + game.scores.total))} + onClose={handleClosePopup} + /> + )} + {loading && ( +
+

Loading prebuilt PCs...

+
+ )} + {error && ( +
+

{error}

+
+ )} +
+ ); +} + +export default SelectGameAndBudgetPage; \ No newline at end of file diff --git a/client/src/pages/Shopping_cart/CartPage.jsx b/client/src/pages/Shopping_cart/CartPage.jsx new file mode 100644 index 0000000..e983526 --- /dev/null +++ b/client/src/pages/Shopping_cart/CartPage.jsx @@ -0,0 +1,111 @@ +import React from "react"; +import { useSelector, useDispatch } from "react-redux"; +import { removeFromCart, increaseQuantity, decreaseQuantity } from "../../redux/cartSlice"; +import { Button, IconButton } from "@mui/material"; +import { Add, Remove, Delete } from "@mui/icons-material"; +import axios from "axios" +import { useNavigate } from "react-router-dom"; +import PaymentGateway from "./PaymentGateway"; +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar" +import Footer from "../../MoleculesComponents/User_navbar_and_footer/Footer" + + + + +const CartPage = () => { + const cartItems = useSelector((state) => state.cart.cartItems); + const totalPrice = useSelector((state) => state.cart.totalPrice); + const dispatch = useDispatch(); + + const navigate = useNavigate(); + + const handleClick = () => { + navigate(`/paymentgateway`); // Redirect to ItemPage + }; + + + return ( + +
+
+
+ {/* Title */} +

+ QUOTATION +

+ + {/* Cart Items List */} + {cartItems.length === 0 ? ( +

Your cart is empty

+ ) : ( +
+ {cartItems.map((item) => ( +
+ {/* Product Image & Name */} +
+ {item.name} +

{item.name}

+
+ + {/* Quantity Control + Price + Remove Button (Horizontally Aligned) */} +
+ {/* Quantity Control */} +
+ dispatch(decreaseQuantity(item._id))} + disabled={item.quantity <= 1} + className="border border-gray-300 rounded" + > + + + {item.quantity} + dispatch(increaseQuantity(item._id))} + className="border border-gray-300 rounded" + > + + +
+ + {/* Price */} +

+ {(item.price * item.quantity).toLocaleString()} LKR +

+ + {/* Remove Button */} + dispatch(removeFromCart(item))} + className="text-red-500" + > + + +
+
+ ))} +
+ )} + + {/* Grand Total & Checkout */} +
+

+ Grand Total: {totalPrice.toLocaleString()} LKR +

+ +
+
+
+
+ ); +}; + +export default CartPage; diff --git a/client/src/pages/Shopping_cart/PaymentGateway.jsx b/client/src/pages/Shopping_cart/PaymentGateway.jsx new file mode 100644 index 0000000..24df04e --- /dev/null +++ b/client/src/pages/Shopping_cart/PaymentGateway.jsx @@ -0,0 +1,243 @@ +import React from "react"; +import { useSelector, useDispatch } from "react-redux"; +import { removeFromCart, increaseQuantity, decreaseQuantity } from "../../redux/cartSlice"; +import { Button, IconButton } from "@mui/material"; +import { Add, Remove, Delete, Label } from "@mui/icons-material"; + +import Navbar from "../../MoleculesComponents/User_navbar_and_footer/Navbar"; +import Footer from "../../MoleculesComponents/User_navbar_and_footer/Footer"; + +import { loadStripe } from "@stripe/stripe-js"; +import { Elements, CardElement, useStripe, useElements } from "@stripe/react-stripe-js"; + +const stripePromise = loadStripe("pk_test_51RAt66QrMZYW3Chd7hWi12tUhngYuiEe7M1hBUpvJAHIIZq95xF9yo97ZQBuup7avOuiTojlhqxm3R0GbxAmNexx00e2V1MOzb"); // Replace with your Stripe test publishable key + +const PaymentGateway = () => { + const cartItems = useSelector((state) => state.cart.cartItems) || []; + const totalPrice = useSelector((state) => state.cart.totalPrice) || 0; + + const handleCheckout = async (paymentMethodId) => { + try { + const sanitizedCartItems = cartItems.map((item) => ({ + _id: item._id || item.Id, + name: item.name, + category: item.type, + quantity: item.quantity, + price: item.price, + })); + + console.log("Sending Checkout Request:", { items: sanitizedCartItems, total: totalPrice }); + + const response = await fetch("http://localhost:8000/api/checkout", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ items: sanitizedCartItems, total: totalPrice, paymentMethodId }), + }); + + const data = await response.json(); + console.log("Server Response:", data); + + if (response.ok) { + alert("Transaction Successful! 🎉"); + } else { + alert(`Transaction Failed: ${data.message}`); + } + } catch (error) { + console.error("Checkout Error:", error); + alert("Transaction Failed! Please try again."); + } + }; + + return ( +
+
+ +
+
+ {/* Title */} +

+ PAYMENT GATEWAY +

+ + {/* Cart Items List */} + {cartItems.length === 0 ? ( +

Your cart is empty

+ ) : ( +
+ {cartItems.map((item) => ( +
+ {/* Product Image & Name */} +
+ {item.name} +

{item.name}

+
+ + {/* Quantity Control + Price + Remove */} +
+
+ + {item.quantity} + +
+ +

+ {(item.price * item.quantity).toLocaleString()} LKR +

+ + +
+
+ ))} +
+ )} + + {/* Total & Checkout */} + {cartItems.length > 0 && ( +
+

+ Total: {totalPrice.toLocaleString()} LKR +

+ + + +
+ )} +
+
+
+
+
+ ); +}; + +const CheckoutForm = ({ onCheckout }) => { + const stripe = useStripe(); + const elements = useElements(); + + const [formData, setFormData] = React.useState({ + name: "", + address: "", + phone: "", + email: "", + }); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + if (!stripe || !elements) { + return; + } + + const cardElement = elements.getElement(CardElement); + + const { paymentMethod, error } = await stripe.createPaymentMethod({ + type: "card", + card: cardElement, + billing_details: { + name: formData.name, + email: formData.email, + phone: formData.phone, + address: { + line1: formData.address, + }, + }, + }); + + if (error) { + console.error("Payment Method Error:", error); + alert("Payment failed. Please try again."); + } else { + onCheckout(paymentMethod.id); + } + }; + + const cardElementOptions = { + hidePostalCode: true, + style: { + base: { + fontSize: "16px", + color: "#32325d", + "::placeholder": { + color: "#aab7c4", + }, + }, + invalid: { + color: "#fa755a", + }, + }, + }; + + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ ); +}; + +export default PaymentGateway; \ No newline at end of file diff --git a/client/src/pages/Single_Item/Itempage.css b/client/src/pages/Single_Item/Itempage.css new file mode 100644 index 0000000..b2b14c5 --- /dev/null +++ b/client/src/pages/Single_Item/Itempage.css @@ -0,0 +1,45 @@ + +@import url('https://fonts.googleapis.com/css?family=Roboto'); + + + + +#itempath{ + + + padding-left: 2cm; + padding-right:cm ; + padding-top:1cm ; + padding-bottom: ; + margin-top: ; + margin-bottom: ; + margin-left: ; + margin-right: 21cm; + + +} + +#pathonly{ + word-spacing: 1px; + color: rgb(96, 97, 99); +} +#realitem{ + font-size: 17px; + color: black; + padding-left: cm; + padding-right:cm ; + padding-top:cm ; + padding-bottom: ; + margin-top:-0.56cm ; + margin-bottom: ; + margin-left: 7.2cm; + margin-right: -1cm; + font-weight: 500; + +} + + + + + + diff --git a/client/src/pages/Single_Item/Itempage.jsx b/client/src/pages/Single_Item/Itempage.jsx new file mode 100644 index 0000000..a65cfee --- /dev/null +++ b/client/src/pages/Single_Item/Itempage.jsx @@ -0,0 +1,82 @@ +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import Itempath from './components/Itempath'; + +import Itemimage from './components/Itemimage'; +import ProductTabs from './components/Itemdiscription'; +import Itemrelates from './components/Itemrelates'; +import Navbar from '../../MoleculesComponents/User_navbar_and_footer/Navbar'; +import Footer from '../../MoleculesComponents/User_navbar_and_footer/Footer'; +import Itemspecs from './components/Itemspecs'; + + + + + + +export default function Itempage() { + + + + const { id } = useParams(); {/* get paticular data from id */} + const [product, setProduct] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + + + + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await fetch(`api/product/${id}`); + if (!response.ok) { + throw new Error('Failed to fetch product'); + } + const data = await response.text(); + setProduct(data); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + fetchProduct(); + }, [id]); + + if (loading) return

Loading...

; + if (error) return

Error: {error}

; + if (!product) return

Product not found

; + + return ( +
+ + + +
+

{product.name}

+
+ +
+ {/*individual item images are Here..basically 2 images */} +
+ + + + {/* className="mt-[-560px] ml-[550px]" */} +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ ); +} \ No newline at end of file diff --git a/client/src/pages/Single_Item/components/Itemdiscription.jsx b/client/src/pages/Single_Item/components/Itemdiscription.jsx new file mode 100644 index 0000000..ddf207d --- /dev/null +++ b/client/src/pages/Single_Item/components/Itemdiscription.jsx @@ -0,0 +1,124 @@ +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; + + + + + + +export default function ProductTabs() { + + + const { id } = useParams(); // Get product ID from URL + const [product, setProduct] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await axios.get(`http://localhost:8000/api/product/${id}`); + setProduct(response.data); + } catch (err) { + setError('Failed to load product'); + } finally { + setLoading(false); + } + }; + + fetchProduct(); + }, [id]); + + + const [activeTab, setActiveTab] = useState("specification"); + + + if (loading) return

Loading product...

; + if (error) return

{error}

; + if (!product) return

Product not found

; + + + + + + + + + return ( + + +
+ + + {/* Tab Headers (Centered) */} +
+ + + + + + + +
+ + {/* Tab Content */} +
+ {activeTab === "specification" ? ( +
+

+ {product.description} +

+ + {/*

{product.description}

*/} +

+ {product.description} +

+ +

+ {product.description} +

+ +

+ Categories: {product.type} +

+
+ ) : ( +
+

{product.description}

+

+ ⭐⭐⭐⭐⭐ - {product.description} -{" "} + John D. +

+

+ ⭐⭐⭐⭐ - {product.description} -{" "} + Alice W. +

+

+ ⭐⭐⭐⭐⭐ - {product.description} -{" "} + Mark R. +

+
+ )} +
+
+ ); +} diff --git a/client/src/pages/Single_Item/components/Itemimage.jsx b/client/src/pages/Single_Item/components/Itemimage.jsx new file mode 100644 index 0000000..7656980 --- /dev/null +++ b/client/src/pages/Single_Item/components/Itemimage.jsx @@ -0,0 +1,74 @@ +import React, { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import axios from "axios"; + +export default function Itemimage() { + const { id } = useParams(); // Get product ID from URL + const [product, setProduct] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [Mainimage, setMainImage] = useState(null); // Initialize as null + + // Fetch product data + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await axios.get(`http://localhost:8000/api/product/${id}`); + setProduct(response.data); + } catch (err) { + setError("Failed to load product"); + } finally { + setLoading(false); + } + }; + + fetchProduct(); + }, [id]); + + // Update Mainimage when product data is fetched + useEffect(() => { + if (product?.imgUrls?.[0]?.url) { + setMainImage(product?.imgUrls?.[0]?.url); // Set main image to image1 when available + } + }, [product]); + + if (loading) return

Loading product...

; + if (error) return

{error}

; + if (!product) return

Product not found

; + + // Fallback image in case `product.image1` is missing + const defaultImage = "../graph1.png"; + const imageArray = [product?.imgUrls?.[0]?.url || defaultImage, defaultImage]; + + return ( +
+ {/* Main Image */} +
+ {product.name} +
+ + {/* Thumbnails */} +
+ {imageArray.map((img, index) => ( + + ))} +
+
+ ); +} diff --git a/client/src/pages/Single_Item/components/Itempath.jsx b/client/src/pages/Single_Item/components/Itempath.jsx new file mode 100644 index 0000000..bbab689 --- /dev/null +++ b/client/src/pages/Single_Item/components/Itempath.jsx @@ -0,0 +1,87 @@ +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; + + +export default function Itempath() { + + + const { id } = useParams(); // Get product ID from URL + const [product, setProduct] = useState(true); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await axios.get(`http://localhost:8000/api/product/${id}`); + setProduct(response.data); + } catch (err) { + setError('Failed to load product'); + } finally { + setLoading(false); + } + }; + + fetchProduct(); + }, [id]); + + + // const getCategoryLabel = (type) => { + // for (const category in subCategories) { + // const found = subCategories[category].find(item => item.value === type); + // if (found) return found.label; + // } + // }; + + + const myArray = [ + + { label: 'Home', href: '/' }, + { label: product.type, href: `/productcategorypage/${product.type}` }, + { label: product.name , href: '#' } + + + ] ; + + + + + + + if (loading) return

Loading product...

; + if (error) return

{error}

; + if (!product) return

Product not found

; + + + + + + + + + + return ( + + ); +} + + + diff --git a/client/src/pages/Single_Item/components/Itemrelates.jsx b/client/src/pages/Single_Item/components/Itemrelates.jsx new file mode 100644 index 0000000..55273d7 --- /dev/null +++ b/client/src/pages/Single_Item/components/Itemrelates.jsx @@ -0,0 +1,86 @@ +import React from 'react' + + + + +export default function Itemrelates() { + const products = [ + { + id: 1, + name: "Intel® Core Ultra 7 Processor 265K", + brand: "Intel", + price: "134,000 LKR", + image: "/images/ultra7.png", + }, + { + id: 2, + name: "Intel Core Ultra 5 Processor 245K", + brand: "Intel", + price: "110,000 LKR", + image: "/images/ultra5.png", + }, + { + id: 3, + name: "Intel Core i9 14900K (36M Cache, up to 6.00 GHz)", + brand: "Intel", + price: "165,000 LKR", + image: "/images/i9-14900K.png", + }, + { + id: 4, + name: "Intel Core i9 14900KS (36M Cache, up to 6.20 GHz)", + brand: "Intel", + price: "225,000 LKR", + image: "/images/i9-14900KS.png", + }, + { + id: 5, + name: "MSI GEFORCE RTX™ 3060 GAMING X 12GB", + brand: "ASUS", + price: "136,000 LKR", + image: "/images/rtx-3060.png", + }, + ]; + + return ( +
+ {/* Header */} +

+ Related Products +

+ + {/* Products Grid */} +
+ {products.map((product) => ( +
+ {/* Product Image */} + {product.name} + + {/* Product Name */} +

+ {product.name} +

+ + {/* Brand */} +

+ Brand: {product.brand} +

+ + {/* Price */} +

+ {product.price} +

+
+ ))} +
+
+ ); + } + diff --git a/client/src/pages/Single_Item/components/Itemspecs.jsx b/client/src/pages/Single_Item/components/Itemspecs.jsx new file mode 100644 index 0000000..8b01ec2 --- /dev/null +++ b/client/src/pages/Single_Item/components/Itemspecs.jsx @@ -0,0 +1,164 @@ +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; + + + + + + + +export default function Itemspecs() { + + + + + const { id } = useParams(); // Get product ID from URL + const [product, setProduct] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchProduct = async () => { + try { + const response = await axios.get(`http://localhost:8000/api/product/${id}`); + setProduct(response.data); + } catch (err) { + setError('Failed to load product'); + } finally { + setLoading(false); + } + }; + + fetchProduct(); + }, [id]); + + + + if (loading) return

Loading product...

; + if (error) return

{error}

; + if (!product) return

Product not found

; + + + + var spec1; //x + var spec2; //y + var spec3; //z + var spec4; //p + var spec5; //q for warranty + var spec6; // + + var x; + var y; + var z; + var p; + var q; + var r; + + switch (product.type) { + case "graphiccard": + + spec1 = "Brand:"; + spec2 = "Capacity:"; + spec3 = "PCI:"; + spec4 = "Speed:"; + spec5 ="Warranty:"; + spec6 = "Oveclock Speed:" + + x = product.manufacturer; + y = product.capacity; + z = product.pcibus; + p = product.pcibus; + q = product.warranty; + r = product.warranty + + + break; + + + case "processor": + spec1 = "Brand:"; //x + spec2 = "Cores:"; //y + spec3 = "Threads:"; //z + spec6 = "Frequency:" //r + spec4 = "Cache:"; //p + spec5 ="Warranty:"; //q + + + x = product.brand; + y = product.cores; + z = product.threads; + r = product.cache; + p = product.speed; + q = product.warranty; + + break; + + case "ram": + spec1 = "Brand:"; //x + spec2 = "Capacity:"; //y + spec3 = "Type:"; //z + spec6 = "Speed:" //r + spec4 = "Cache:"; //p + spec5 ="Warranty:"; //q + + + x = product.manufacturer; + y = product.memoryCapacity; + z = product.memoryType; + r = product.memorySpeed; + p = product.memoryType; + q = product.memoryCapacity; + + break; + + + + default: + break; + } + + + return ( + +
+
+

+ {product.name} +

+ +
+

{spec1} {x}

+

{spec2} {y}

+

{spec3} {z}

+

{spec4} {p}MB

+

{spec6} {r}GHz

+

{spec5} {q} Years

+
+ + +
+ {product.price} LKR +
+ +
+ + {product.quantity> 0 ? "In Stock" : "Out of Stock"} + +
+ +
+ + +
+
+
+ ); +} diff --git a/client/src/pages/Testing.jsx b/client/src/pages/Testing.jsx new file mode 100644 index 0000000..4dac50d --- /dev/null +++ b/client/src/pages/Testing.jsx @@ -0,0 +1,189 @@ +import { Outlet } from "react-router-dom"; +import Iconset from "../AtomicComponents/Icons/Iconset"; +import theme from "../AtomicComponents/theme"; +import { DashboardLayout } from "@toolpad/core"; + +const NAVIGATION = [ + { + kind: "header", + title: "Main", + }, + { + segment: "dashboard", + title: "Dashboard", + icon: , + }, + { + segment: "admin", + title: "Admin", + icon: , + children: [ + { + segment: "profile", + title: "Profile", + icon: , + }, + { + segment: "setting", + title: "Settings", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: 'header', + title: 'Games', + }, + { + segment: 'games', + title: 'Games', + icon: , // Reuse an existing icon or create a new one + children: [ + { + segment: 'managegames', + title: 'Manage Games', + icon: , // Reuse or replace with a game-specific icon + }, + { + segment: 'creategame', + title: 'Create Game', + icon: , // Reuse or replace with a game-specific icon + }, + ], + }, + + + { + kind: "header", + title: "Product & Order", + }, + { + segment: "products", + title: "Products", + icon: , + children: [ + { + segment: "manageproduct", + title: "Manage Product", + icon: , + }, + { + segment: "createproduct", + title: "Create Product", + icon: , + }, + ], + }, + { + segment: "orders", + title: "Orders ", + icon: , + children: [ + { + segment: "orderlist", + title: "Order List", + icon: , + }, + { + segment: "receiveorder", + title: "Received Order", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: "header", + title: "User Section", + }, + { + segment: "usermanage", + title: "User Manage", + icon: , + }, + { + kind: "divider", + }, + { + kind: "header", + title: "Feedbacks", + }, + { + segment: "feedbackmanage", + title: "Feedback Manage", + icon: , + children: [ + { + segment: "complaints", + title: "Complaints", + icon: , + }, + { + segment: "comments&reviews", + title: "Comments & Reviews", + icon: , + }, + { + segment: "rma", + title: "RMA", + icon: , + }, + ], + }, + { + kind: "divider", + }, + { + kind: "header", + title: "Invoices", + }, + { + segment: "invoice", + title: "Invoice ", + icon: , + children: [ + { + segment: "invoicelist", + title: "Invoice List", + icon: , + }, + { + segment: "invoicecreate", + title: "Create Invoice", + icon: , + }, + ], + }, +]; + +export default function Testing() { + return ( + + ), + title: "", + }} + theme={theme} + > + + + ); +} \ No newline at end of file diff --git a/client/src/redux/cartSlice.js b/client/src/redux/cartSlice.js new file mode 100644 index 0000000..89144b3 --- /dev/null +++ b/client/src/redux/cartSlice.js @@ -0,0 +1,95 @@ +import { createSlice } from "@reduxjs/toolkit"; + +// Try to load from localStorage first +const loadCartFromStorage = () => { + try { + const storedCart = localStorage.getItem("cartState"); + return storedCart ? JSON.parse(storedCart) : { cartItems: [], totalPrice: 0 }; + } catch (e) { + return { cartItems: [], totalPrice: 0 }; + } +}; + +// Save to localStorage +const saveCartToStorage = (state) => { + localStorage.setItem("cartState", JSON.stringify(state)); +}; + +const initialState = loadCartFromStorage(); + +const cartSlice = createSlice({ + name: "cart", + initialState, + reducers: { + addToCart: (state, action) => { + const item = action.payload; + + // Ensure cartItems exists and is an array + if (!Array.isArray(state.cartItems)) { + state.cartItems = []; + } + + const existingItem = state.cartItems.find((i) => i._id === item._id); + + if (existingItem) { + existingItem.quantity += 1; + } else { + state.cartItems.push({ ...item, quantity: 1 }); + } + + // Recalculate total price + state.totalPrice = state.cartItems.reduce( + (sum, item) => sum + item.price * item.quantity, + 0 + ); + + saveCartToStorage(state); + }, + + removeFromCart: (state, action) => { + state.cartItems = state.cartItems.filter( + (item) => item._id !== action.payload._id + ); + + state.totalPrice = state.cartItems.reduce( + (sum, item) => sum + item.price * item.quantity, + 0 + ); + + saveCartToStorage(state); + }, + + increaseQuantity: (state, action) => { + const item = state.cartItems.find((i) => i._id === action.payload); + if (item) item.quantity += 1; + + state.totalPrice = state.cartItems.reduce( + (sum, item) => sum + item.price * item.quantity, + 0 + ); + + saveCartToStorage(state); + }, + + decreaseQuantity: (state, action) => { + const item = state.cartItems.find((i) => i._id === action.payload); + if (item && item.quantity > 1) item.quantity -= 1; + + state.totalPrice = state.cartItems.reduce( + (sum, item) => sum + item.price * item.quantity, + 0 + ); + + saveCartToStorage(state); + }, + }, +}); + +export const { + addToCart, + removeFromCart, + increaseQuantity, + decreaseQuantity, +} = cartSlice.actions; + +export default cartSlice.reducer; diff --git a/client/src/redux/store.js b/client/src/redux/store.js new file mode 100644 index 0000000..b112a8c --- /dev/null +++ b/client/src/redux/store.js @@ -0,0 +1,8 @@ +import { configureStore } from '@reduxjs/toolkit'; +import cartReducer from './cartSlice'; + +export const store = configureStore({ + reducer: { + cart: cartReducer, + }, +}); diff --git a/client/src/utils/scoreCalculator.js b/client/src/utils/scoreCalculator.js new file mode 100644 index 0000000..213cb94 --- /dev/null +++ b/client/src/utils/scoreCalculator.js @@ -0,0 +1,79 @@ +// src/utils/scoreCalculator.js +export function calculateCPUScore({ cores, threads, baseClock, boostClock, brand = 'Generic' }) { + const rawScore = (cores * 10) + (threads * 5) + (baseClock * 15) + (boostClock * 20); + return rawScore; +} + +export function calculateGPUScore({ vramGB, boostClockMHz, cores, series = '', brand = 'Generic' }) { + const rawScore = (vramGB * 8) + (boostClockMHz / 50) + (cores / 100); + const normalizedSeries = normalizeGPUSeries(series); + const seriesBonus = { + GTX: 0.9, + 'RTX 20': 1.0, + 'RTX 30': 1.1, + 'RTX 40': 1.2, + 'RX 5000': 1.0, + 'RX 6000': 1.1, + 'RX 7000': 1.2, + 'ARC A': 1.0, + }; + const bonus = seriesBonus[normalizedSeries] || 1.0; + return rawScore * bonus; +} + +export function calculateRAMScore({ sizeGB, speedMHz, type = 'DDR4' }) { + const typeMultiplier = type.toUpperCase() === 'DDR5' ? 1.1 : 1.0; + const score = ((sizeGB / 64) * 60) + ((speedMHz / 6000) * 40); + return score * typeMultiplier; +} + +export function calculateTotalScore(cpuScore, gpuScore, ramScore) { + return parseFloat(((cpuScore * 0.3) + (gpuScore * 0.5) + (ramScore * 0.2)).toFixed(2)); +} + +function normalizeGPUSeries(series) { + if (!series) return ''; + const upperSeries = series.toUpperCase(); + if (upperSeries.includes('GTX')) return 'GTX'; + if (upperSeries.includes('RTX 20')) return 'RTX 20'; + if (upperSeries.includes('RTX 30') || upperSeries.includes('3060') || upperSeries.includes('3070') || upperSeries.includes('3080') || upperSeries.includes('3090')) return 'RTX 30'; + if (upperSeries.includes('RTX 40') || upperSeries.includes('4090') || upperSeries.includes('4080') || upperSeries.includes('4070')) return 'RTX 40'; + if (upperSeries.includes('RX 5')) return 'RX 5000'; + if (upperSeries.includes('RX 6') || upperSeries.includes('6700') || upperSeries.includes('6800') || upperSeries.includes('6900')) return 'RX 6000'; + if (upperSeries.includes('RX 7') || upperSeries.includes('7900') || upperSeries.includes('7800') || upperSeries.includes('7700')) return 'RX 7000'; + if (upperSeries.includes('ARC') || upperSeries.includes('A770') || upperSeries.includes('A750')) return 'ARC A'; + return ''; +} + +// New function to calculate scores for prebuilt PCs +export function calculatePrebuiltPcScore(prebuilt) { + const cpuData = { + cores: parseFloat(prebuilt.cpuCores) || 0, + threads: parseFloat(prebuilt.cpuThreads) || 0, + baseClock: parseFloat(prebuilt.cpuBaseClock) || 0, + boostClock: parseFloat(prebuilt.cpuBoostClock) || 0, + }; + const gpuData = { + vramGB: parseFloat(prebuilt.gpuVramGb) || 0, + boostClockMHz: parseFloat(prebuilt.gpuBoostClockMhz) || 0, + cores: parseFloat(prebuilt.gpuCores) || 0, + series: prebuilt.gpuSeries || '', + }; + const ramData = { + sizeGB: parseFloat(prebuilt.ramSizeGb) || 0, + speedMHz: parseFloat(prebuilt.ramSpeedMhz) || 0, + type: prebuilt.ramType || 'DDR4', + }; + + const cpuScore = calculateCPUScore(cpuData); + const gpuScore = calculateGPUScore(gpuData); + const ramScore = calculateRAMScore(ramData); + const totalScore = calculateTotalScore(cpuScore, gpuScore, ramScore); + + return { + cpu: cpuScore, + gpu: gpuScore, + ram: ramScore, + total: totalScore, + }; +} \ No newline at end of file diff --git a/client/tailwind.config.js b/client/tailwind.config.js index c189a4a..3218f5b 100644 --- a/client/tailwind.config.js +++ b/client/tailwind.config.js @@ -1,9 +1,15 @@ /** @type {import('tailwindcss').Config} */ export default { - content: [], + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], theme: { - extend: {}, + extend: { + colors: { + 'regal-gray': '#BBB6B6', + }, + }, }, plugins: [], -} - +} \ No newline at end of file diff --git a/client/vite.config.js b/client/vite.config.js index 8b0f57b..8e5315e 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -1,7 +1,12 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; // https://vite.dev/config/ export default defineConfig({ plugins: [react()], -}) + optimizeDeps: { + include: ['@tiptap/react', '@tiptap/starter-kit'], + force: true + } + +}) \ No newline at end of file