From ee8f73c99dd97af3720a5e1050e78bfb1f3ada2b Mon Sep 17 00:00:00 2001 From: KALYANI100 Date: Thu, 26 Mar 2026 15:05:37 +0530 Subject: [PATCH 1/2] New_Pages_added --- package-lock.json | 274 ++++++ package.json | 1 + src/App.jsx | 10 + src/app/config/api.js | 1 + src/app/services/adminAPI.js | 5 +- src/app/services/allocationAPI.js | 6 +- src/app/services/authAPI.js | 6 +- src/app/services/formAPI.js | 6 +- src/app/services/judgeAPI.js | 6 +- src/components/admin/AdminViewAllocation.jsx | 400 +++++++++ src/components/admin/AnalyticsDashboard.jsx | 786 ++++++++++++++++++ .../admin/ProjectJudgeAllocation.jsx | 372 +++++++++ src/components/admin/ProjectReallocate.jsx | 333 ++++++++ src/components/admin/ProjectSchedule.jsx | 325 ++++++++ src/components/navbar.jsx | 8 +- src/constants/index.js | 28 +- 16 files changed, 2546 insertions(+), 21 deletions(-) create mode 100644 src/app/config/api.js create mode 100644 src/components/admin/AdminViewAllocation.jsx create mode 100644 src/components/admin/AnalyticsDashboard.jsx create mode 100644 src/components/admin/ProjectJudgeAllocation.jsx create mode 100644 src/components/admin/ProjectReallocate.jsx create mode 100644 src/components/admin/ProjectSchedule.jsx diff --git a/package-lock.json b/package-lock.json index d1009f5..093af70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "react-redux": "^9.2.0", "react-router-dom": "^7.1.0", "react-toastify": "^11.0.2", + "recharts": "^3.8.0", "tailwind-merge": "^2.6.0", "three": "^0.172.0" }, @@ -2297,6 +2298,69 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/debounce": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.4.tgz", @@ -3251,6 +3315,127 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -3328,6 +3513,12 @@ } } }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3639,6 +3830,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", + "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -3913,6 +4114,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4562,6 +4769,15 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -6247,6 +6463,36 @@ "node": ">=8.10.0" } }, + "node_modules/recharts": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.0.tgz", + "integrity": "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", @@ -7118,6 +7364,12 @@ "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==", "license": "MIT" }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -7435,6 +7687,28 @@ "node": ">= 4" } }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", diff --git a/package.json b/package.json index e9b2050..3ff9343 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "react-redux": "^9.2.0", "react-router-dom": "^7.1.0", "react-toastify": "^11.0.2", + "recharts": "^3.8.0", "tailwind-merge": "^2.6.0", "three": "^0.172.0" }, diff --git a/src/App.jsx b/src/App.jsx index 144dd47..b110b87 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -21,6 +21,11 @@ import GenerateSynopsis from "./components/GenerateSynopsis"; import { AnimatePresence } from "framer-motion"; import Preloader from "./components/Preloader"; +import AdminViewAllocations from "./components/admin/AdminViewAllocation.jsx"; +import ProjectJudgesAllocation from "./components/admin/ProjectJudgeAllocation.jsx"; +import AnalyticsDashboard from "./components/admin/AnalyticsDashboard.jsx"; +import AdminReallocate from "./components/admin/ProjectReallocate.jsx"; +import AdminJudgingSchedule from "./components/admin/ProjectSchedule.jsx"; // Lazy components const Register = lazy(() => import("./components/Register.jsx")); @@ -164,6 +169,11 @@ const App = () => { /> } /> + } /> + } /> + } /> + } /> + } /> } diff --git a/src/app/config/api.js b/src/app/config/api.js new file mode 100644 index 0000000..bac6ed2 --- /dev/null +++ b/src/app/config/api.js @@ -0,0 +1 @@ +export const API_BASE = 'https://api.pictinc.org'; \ No newline at end of file diff --git a/src/app/services/adminAPI.js b/src/app/services/adminAPI.js index 2bc5c31..ba40d16 100644 --- a/src/app/services/adminAPI.js +++ b/src/app/services/adminAPI.js @@ -1,8 +1,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { API_BASE } from '../../app/config/api'; -// const baseURL = ("https://api.pyush.site") + "/events"; -// const baseURL="https://inc-2026-backend.onrender.com" + "/events" -const baseURL = "https://api.pictinc.org/events"; +const baseURL = `${API_BASE}/events`; export const adminAPI = createApi({ reducerPath: "admins", diff --git a/src/app/services/allocationAPI.js b/src/app/services/allocationAPI.js index 0f78221..d1f96d4 100644 --- a/src/app/services/allocationAPI.js +++ b/src/app/services/allocationAPI.js @@ -1,9 +1,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { API_BASE } from '../../app/config/api'; -// const baseURL = ("https://api.pyush.site") + "/allocations"; -// const baseURL = ("https://inc-2026-backend.onrender.com") + "/allocations"; -// const baseURL = "https://inc-2026-backend.onrender.com/allocations"; -const baseURL = "https://api.pictinc.org/allocations"; +const baseURL = `${API_BASE}/allocations`; export const allocationAPI = createApi({ diff --git a/src/app/services/authAPI.js b/src/app/services/authAPI.js index 3f85f59..752d090 100644 --- a/src/app/services/authAPI.js +++ b/src/app/services/authAPI.js @@ -1,9 +1,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { API_BASE } from '../../app/config/api'; -// const baseURL = ("https://api.pyush.site") + "/admin"; -// const baseURL = ("https://inc-2026-backend.onrender.com") + "/admin"; -// const baseURL = "https://inc-2026-backend.onrender.com/admin"; -const baseURL = "https://api.pictinc.org/admin"; +const baseURL = `${API_BASE}/admin`; export const authAPI = createApi({ diff --git a/src/app/services/formAPI.js b/src/app/services/formAPI.js index d31b559..a9fea74 100644 --- a/src/app/services/formAPI.js +++ b/src/app/services/formAPI.js @@ -1,9 +1,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { API_BASE } from '../../app/config/api'; -// const baseURL = ("https://api.pyush.site") + "/events"; -// const baseURL = ("https://inc-2026-backend.onrender.com") + "/events"; -// const baseURL = "https://inc-2026-backend.onrender.com/events"; -const baseURL = "https://api.pictinc.org/events"; +const baseURL = `${API_BASE}/events`; export const formAPI = createApi({ diff --git a/src/app/services/judgeAPI.js b/src/app/services/judgeAPI.js index de556b9..9cb4049 100644 --- a/src/app/services/judgeAPI.js +++ b/src/app/services/judgeAPI.js @@ -1,9 +1,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { API_BASE } from '../../app/config/api'; -// const baseURL = ("https://api.pyush.site") + "/judge"; -// const baseURL = ("https://inc-2026-backend.onrender.com") + "/judge"; -// const baseURL = "https://inc-2026-backend.onrender.com/judge"; -const baseURL = "https://api.pictinc.org/judge"; +const baseURL = `${API_BASE}/judge`; export const judgeAPI = createApi({ reducerPath: "judges", diff --git a/src/components/admin/AdminViewAllocation.jsx b/src/components/admin/AdminViewAllocation.jsx new file mode 100644 index 0000000..869c7d0 --- /dev/null +++ b/src/components/admin/AdminViewAllocation.jsx @@ -0,0 +1,400 @@ +import { useEffect, useState, useMemo } from 'react'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { Chip, Box, Typography, Card, CardContent } from '@mui/material'; +import { API_BASE } from '../../app/config/api'; + +const AdminViewAllocations = () => { + const [activeTab, setActiveTab] = useState('impetus'); + const [filterStatus, setFilterStatus] = useState('all'); + const [rows, setRows] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + // Fetch data from backend + useEffect(() => { + const fetchAllocations = async () => { + setLoading(true); + setError(null); + + try { + const response = await fetch(`${API_BASE}/view/admin/allocations?event=${activeTab}`, { + method: 'GET', // explicitly a GET request + headers: { + 'Content-Type': 'application/json' + }, + credentials: 'include' +}); + if (!response.ok) { + throw new Error('Failed to fetch data'); + } + + const data = await response.json(); + + if (data.success) { + // Transform backend data into DataGrid rows + const newRows = data.judges.map((judge, index) => { + const allocatedPids = judge.allocated_projects + ? judge.allocated_projects.split(',').filter(Boolean) + : []; + + let evaluatedCount = 0; + + const projectData = Array.from({ length: 7 }, (_, i) => { + const pid = allocatedPids[i] || '-'; + + if (pid === '-') { + return { pid: '-', chip: null }; + } + + // Find project from judge.projects array + const project = judge.projects?.find(p => p.pid === pid); + const isEvaluated = project ? project.evaluated : false; + + if (isEvaluated) evaluatedCount++; + + return { + pid, + chip: ( + + ) + }; + }); + + const totalAllocated = allocatedPids.length; + const remaining = totalAllocated - evaluatedCount; + + const rowData = { + id: index, + jid: judge.jid, + name: judge.name, + status: judge.is_online ? 'Online' : 'Offline', + mode: judge.mode, + totalAllocated, + totalEvaluated: evaluatedCount, + remaining, + evaluationStatus: judge.evaluationStatus || 'incomplete', + }; + + // Add project columns dynamically + projectData.forEach((p, i) => { + rowData[`proj${i + 1}`] = p.pid; + rowData[`proj${i + 1}Chip`] = p.chip; + }); + + return rowData; + }); + + setRows(newRows); + } + } catch (err) { + console.error('Error fetching allocations:', err); + setError('Failed to load judge allocations. Please try again later.'); + } finally { + setLoading(false); + } + }; + + fetchAllocations(); + }, [activeTab]); + + // Filtered rows based on status + const filteredRows = useMemo(() => { + if (filterStatus === 'all') return rows; + return rows.filter(row => row.evaluationStatus === filterStatus); + }, [rows, filterStatus]); + + // Summary Counts + const summary = useMemo(() => { + const completed = rows.filter(r => r.evaluationStatus === 'completed').length; + const partial = rows.filter(r => r.evaluationStatus === 'partial').length; + const incomplete = rows.filter(r => r.evaluationStatus === 'incomplete').length; + + return { + total: rows.length, + completed, + partial, + incomplete + }; + }, [rows]); + + const columns = [ + { field: 'jid', headerName: 'JID', width: 100, minWidth: 100 }, + { field: 'name', headerName: 'Judge Name', width: 230, minWidth: 230 }, + { + field: 'status', + headerName: 'Status', + width: 130, + minWidth: 130, + renderCell: (params) => ( + + ● {params.value} + + ), + }, + { field: 'mode', headerName: 'Mode', width: 110, minWidth: 110 }, + + { + field: 'totalEvaluated', + headerName: 'Evaluated', + width: 130, + minWidth: 130, + renderCell: (params) => ( + + {params.value} / {params.row.totalAllocated} + + ), + }, + { + field: 'remaining', + headerName: 'Remaining', + width: 110, + minWidth: 110, + renderCell: (params) => ( + 0 ? "#eab308" : "#22c55e"}> + {params.value} + + ), + }, + + // 7 Project Columns + ...Array.from({ length: 7 }, (_, i) => ({ + field: `proj${i + 1}`, + headerName: `Project ${i + 1}`, + width: 200, + minWidth: 200, + flex: 0, + renderCell: (params) => { + const pid = params.value; + if (pid === '-') { + return -; + } + + const chip = params.row[`proj${i + 1}Chip`]; + + return ( + + + {pid} + + {chip} + + ); + }, + })), + ]; + + if (loading) { + return ( +
+ Loading Judge Allocations... +
+ ); + } + + if (error) { + return ( +
+ {error} +
+ ); + } + + return ( +
+
+

+ Judge Allocations +

+ + {/* Tabs */} +
+
+ + +
+
+ + {/* Summary Cards */} +
+ + + Total Judges + + {summary.total} + + + + + + + Completed + + {summary.completed} + + + + + + + Partially Done + + {summary.partial} + + + + + + + Incomplete + + {summary.incomplete} + + + +
+ + {/* Filter Buttons */} +
+ + + + + + + +
+ + {/* DataGrid */} +
+
+ 100} + sx={{ + border: 'none', + minWidth: 'fit-content', + + '& .MuiDataGrid-cell': { + color: '#e2e8f0', + fontSize: '0.95rem', + borderRight: '1px solid #3f3f46', + padding: '8px 12px', + }, + '& .MuiDataGrid-columnHeader': { + backgroundColor: '#18181b', + color: '#a1a1aa', + fontWeight: 600, + fontSize: '0.95rem', + borderBottom: '2px solid #52525b', + borderRight: '1px solid #3f3f46', + }, + '& .MuiDataGrid-row': { + borderBottom: '1px solid #27272a', + }, + '& .MuiDataGrid-row:hover': { + backgroundColor: '#27272a', + }, + '& .MuiDataGrid-toolbarContainer': { + backgroundColor: '#18181b', + color: '#e2e8f0', + }, + + /* Pagination White Text Fix */ + '& .MuiDataGrid-footerContainer': { + backgroundColor: '#18181b', + color: '#e2e8f0', + }, + '& .MuiTablePagination-root': { + color: '#e2e8f0', + }, + '& .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows, & .MuiTablePagination-select': { + color: '#e2e8f0', + }, + '& .MuiTablePagination-actions button': { + color: '#e2e8f0', + }, + '& .MuiTablePagination-actions button:hover': { + backgroundColor: '#27272a', + color: '#fff', + }, + '& .MuiSelect-icon': { + color: '#e2e8f0', + }, + }} + /> +
+
+
+
+ ); +}; + +export default AdminViewAllocations; \ No newline at end of file diff --git a/src/components/admin/AnalyticsDashboard.jsx b/src/components/admin/AnalyticsDashboard.jsx new file mode 100644 index 0000000..14be3c4 --- /dev/null +++ b/src/components/admin/AnalyticsDashboard.jsx @@ -0,0 +1,786 @@ +// import { useState } from 'react'; +// import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'; + +// // Sample Data Structure +// const initialDomainData = [ +// { domain: "Web Development", dailyProjects: { "2025-03-20": 12, "2025-03-21": 14, "2025-03-22": 10, "2025-03-23": 15, "2025-03-24": 18, "2025-03-25": 20 }, evaluated: 45, partiallyEvaluated: 28, completelyEvaluated: 32, judges: 8 }, +// { domain: "AI/ML", dailyProjects: { "2025-03-20": 8, "2025-03-21": 10, "2025-03-22": 12, "2025-03-23": 9, "2025-03-24": 11, "2025-03-25": 14 }, evaluated: 38, partiallyEvaluated: 22, completelyEvaluated: 28, judges: 6 }, +// { domain: "Mobile Apps", dailyProjects: { "2025-03-20": 6, "2025-03-21": 7, "2025-03-22": 9, "2025-03-23": 8, "2025-03-24": 10, "2025-03-25": 11 }, evaluated: 28, partiallyEvaluated: 18, completelyEvaluated: 22, judges: 5 }, +// { domain: "Cloud Computing", dailyProjects: { "2025-03-20": 5, "2025-03-21": 6, "2025-03-22": 7, "2025-03-23": 8, "2025-03-24": 9, "2025-03-25": 10 }, evaluated: 25, partiallyEvaluated: 15, completelyEvaluated: 20, judges: 4 }, +// { domain: "Cybersecurity", dailyProjects: { "2025-03-20": 4, "2025-03-21": 5, "2025-03-22": 6, "2025-03-23": 7, "2025-03-24": 8, "2025-03-25": 9 }, evaluated: 22, partiallyEvaluated: 12, completelyEvaluated: 18, judges: 4 } +// ]; + +// const geographicData = { +// outsideMaharashtra: 28, +// fromMaharashtra: 72, +// international: 15, +// national: 85, +// withinPune: 45, +// outsidePune: 55 +// }; + +// const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec489a']; + +// const AnalyticsDashboard = () => { +// const [domainData] = useState(initialDomainData); + +// // Prepare data for daily allocated projects across domains +// const getAllDates = () => { +// const datesSet = new Set(); +// domainData.forEach(domain => { +// Object.keys(domain.dailyProjects).forEach(date => datesSet.add(date)); +// }); +// return Array.from(datesSet).sort(); +// }; + +// const dates = getAllDates(); + +// const getDailyProjectData = () => { +// return dates.map(date => { +// const dataPoint = { date }; +// domainData.forEach(domain => { +// dataPoint[domain.domain] = domain.dailyProjects[date] || 0; +// }); +// return dataPoint; +// }); +// }; + +// const dailyProjectData = getDailyProjectData(); + +// // Prepare evaluation summary data +// const evaluationData = domainData.map(domain => ({ +// domain: domain.domain, +// Evaluated: domain.evaluated, +// PartiallyEvaluated: domain.partiallyEvaluated, +// CompletelyEvaluated: domain.completelyEvaluated +// })); + +// // Pie data for geographic distribution +// const locationTypeData = [ +// { name: 'Outside Maharashtra', value: geographicData.outsideMaharashtra }, +// { name: 'From Maharashtra', value: geographicData.fromMaharashtra } +// ]; + +// const scopeData = [ +// { name: 'International', value: geographicData.international }, +// { name: 'National', value: geographicData.national } +// ]; + +// const puneData = [ +// { name: 'Within Pune', value: geographicData.withinPune }, +// { name: 'Outside Pune', value: geographicData.outsidePune } +// ]; + +// // Calculate totals for cards +// const totalProjectsAllocated = domainData.reduce((sum, domain) => { +// const dailySum = Object.values(domain.dailyProjects).reduce((a, b) => a + b, 0); +// return sum + dailySum; +// }, 0); + +// const totalEvaluated = domainData.reduce((sum, domain) => sum + domain.evaluated, 0); +// const totalPartiallyEvaluated = domainData.reduce((sum, domain) => sum + domain.partiallyEvaluated, 0); +// const totalCompletelyEvaluated = domainData.reduce((sum, domain) => sum + domain.completelyEvaluated, 0); +// const totalJudges = domainData.reduce((sum, domain) => sum + domain.judges, 0); + +// return ( +//
+// {/* Header */} +//
+//

📊 Project Evaluation Analytics Dashboard

+//

Domain-wise tracking | Judge metrics | Geographic insights

+//
+ +// {/* KPI Cards Row */} +//
+//
+//
+//
+//

Total Allocated Projects

+//

{totalProjectsAllocated}

+//
+// +//
+//
+ +//
+//
+//
+//

Evaluated Projects

+//

{totalEvaluated}

+//
+// +//
+//
+ +//
+//
+//
+//

Partially Evaluated

+//

{totalPartiallyEvaluated}

+//
+// +//
+//
+ +//
+//
+//
+//

Completely Evaluated

+//

{totalCompletelyEvaluated}

+//
+// +//
+//
+ +//
+//
+//
+//

Total Judges (All Domains)

+//

{totalJudges}

+//
+// +//
+//
+//
+ +// {/* Charts Section: Bar Chart for Daily Allocated Projects */} +//
+//
+//

Daily Allocated Projects (Per Domain)

+// +// +// +// +// +// +// +// {domainData.map((domain, idx) => ( +// +// ))} +// +// +//

Daily projects allocated across domains (last 6 days)

+//
+ +// {/* Evaluation Status Stacked Bar */} +//
+//

Evaluation Summary: Evaluated / Partially / Completely

+// +// +// +// +// +// +// +// +// +// +// +// +//

Horizontal stacked view: total evaluated projects breakdown per domain

+//
+//
+ +// {/* Domain-wise Judges Cards */} +//
+//

Judges per Domain

+//
+// {domainData.map((domain, idx) => ( +//
+// +//

{domain.domain}

+//

{domain.judges}

+//

Active Judges

+//
+// ))} +//
+//
+ +// {/* Geographic Analytics: Cards + Pie Charts */} +//
+// {/* Maharashtra vs Outside Maharashtra Card + Pie */} +//
+//

Maharashtra Origin

+//
+//
+//

Outside Maharashtra

+//

{geographicData.outsideMaharashtra}

+//
+//
+//

From Maharashtra

+//

{geographicData.fromMaharashtra}

+//
+//
+//
+// +// +// `${name}: ${(percent * 100).toFixed(0)}%`}> +// {locationTypeData.map((entry, index) => ( +// +// ))} +// +// +// +// +//
+//

Intern/participant distribution by Maharashtra state

+//
+ +// {/* International vs National Card */} +//
+//

International vs National

+//
+//
+//

International

+//

{geographicData.international}

+//
+//
+//

National

+//

{geographicData.national}

+//
+//
+//
+// +// +// `${name}: ${(percent * 100).toFixed(0)}%`}> +// {scopeData.map((entry, index) => ( +// +// ))} +// +// +// +// +//
+//

Scope: International participants vs National participants

+//
+ +// {/* Within Pune vs Outside Pune Card */} +//
+//

Pune Region Distribution

+//
+//
+//

Within Pune

+//

{geographicData.withinPune}

+//
+//
+//

Outside Pune

+//

{geographicData.outsidePune}

+//
+//
+//
+// +// +// `${name}: ${(percent * 100).toFixed(0)}%`}> +// {puneData.map((entry, index) => ( +// +// ))} +// +// +// +// +//
+//

Based on intern / participant location (Pune district)

+//
+//
+ +// {/* Additional Summary Cards for quick stats */} +//
+//
+// +//
+//

Total Domain Categories

+//

{domainData.length}

+//
+//
+//
+// +//
+//

Avg. Completion Rate

+//

{Math.round((totalCompletelyEvaluated / (totalEvaluated || 1)) * 100)}%

+//
+//
+//
+// +//
+//

Judges to Projects Ratio

+//

{(totalProjectsAllocated / totalJudges).toFixed(1)}

+//
+//
+//
+ +// {/* Detailed Domain Table (extra info) */} +//
+//
+//

Domain-wise Detailed Metrics

+//
+//
+// +// +// +// +// +// +// +// +// +// +// +// +// {domainData.map((domain) => { +// const totalAllocatedDomain = Object.values(domain.dailyProjects).reduce((a, b) => a + b, 0); +// return ( +// +// +// +// +// +// +// +// +// ); +// })} +// +//
DomainTotal Allocated (Last 6d)EvaluatedPartially Eval.Completely Eval.Judges Count
{domain.domain}{totalAllocatedDomain}{domain.evaluated}{domain.partiallyEvaluated}{domain.completelyEvaluated}{domain.judges}
+//
+//
+ +//
+//

Analytics Dashboard — Real-time domain insights | Project evaluation status | Geographic segmentation (Maharashtra, Pune, National/International)

+//
+//
+// ); +// }; + +// export default AnalyticsDashboard; + +import { useState } from 'react'; +import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'; + +// Sample Data Structure +const initialDomainData = [ + { domain: "Web Development", dailyProjects: { "2025-03-20": 12, "2025-03-21": 14, "2025-03-22": 10, "2025-03-23": 15, "2025-03-24": 18, "2025-03-25": 20 }, evaluated: 45, partiallyEvaluated: 28, completelyEvaluated: 32, judges: 8 }, + { domain: "AI/ML", dailyProjects: { "2025-03-20": 8, "2025-03-21": 10, "2025-03-22": 12, "2025-03-23": 9, "2025-03-24": 11, "2025-03-25": 14 }, evaluated: 38, partiallyEvaluated: 22, completelyEvaluated: 28, judges: 6 }, + { domain: "Mobile Apps", dailyProjects: { "2025-03-20": 6, "2025-03-21": 7, "2025-03-22": 9, "2025-03-23": 8, "2025-03-24": 10, "2025-03-25": 11 }, evaluated: 28, partiallyEvaluated: 18, completelyEvaluated: 22, judges: 5 }, + { domain: "Cloud Computing", dailyProjects: { "2025-03-20": 5, "2025-03-21": 6, "2025-03-22": 7, "2025-03-23": 8, "2025-03-24": 9, "2025-03-25": 10 }, evaluated: 25, partiallyEvaluated: 15, completelyEvaluated: 20, judges: 4 }, + { domain: "Cybersecurity", dailyProjects: { "2025-03-20": 4, "2025-03-21": 5, "2025-03-22": 6, "2025-03-23": 7, "2025-03-24": 8, "2025-03-25": 9 }, evaluated: 22, partiallyEvaluated: 12, completelyEvaluated: 18, judges: 4 } +]; + +const geographicData = { + outsideMaharashtra: 28, + fromMaharashtra: 72, + international: 15, + national: 85, + withinPune: 45, + outsidePune: 55 +}; + +const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec489a']; + +// Reusable Dashboard Content Component +const DashboardContent = ({ domainData, geographicData, colors }) => { + // Prepare data for daily allocated projects across domains + const getAllDates = () => { + const datesSet = new Set(); + domainData.forEach(domain => { + Object.keys(domain.dailyProjects).forEach(date => datesSet.add(date)); + }); + return Array.from(datesSet).sort(); + }; + + const dates = getAllDates(); + + const getDailyProjectData = () => { + return dates.map(date => { + const dataPoint = { date }; + domainData.forEach(domain => { + dataPoint[domain.domain] = domain.dailyProjects[date] || 0; + }); + return dataPoint; + }); + }; + + const dailyProjectData = getDailyProjectData(); + + // Prepare evaluation summary data + const evaluationData = domainData.map(domain => ({ + domain: domain.domain, + Evaluated: domain.evaluated, + PartiallyEvaluated: domain.partiallyEvaluated, + CompletelyEvaluated: domain.completelyEvaluated + })); + + // Pie data for geographic distribution + const locationTypeData = [ + { name: 'Outside Maharashtra', value: geographicData.outsideMaharashtra }, + { name: 'From Maharashtra', value: geographicData.fromMaharashtra } + ]; + + const scopeData = [ + { name: 'International', value: geographicData.international }, + { name: 'National', value: geographicData.national } + ]; + + const puneData = [ + { name: 'Within Pune', value: geographicData.withinPune }, + { name: 'Outside Pune', value: geographicData.outsidePune } + ]; + + // Calculate totals for cards + const totalProjectsAllocated = domainData.reduce((sum, domain) => { + const dailySum = Object.values(domain.dailyProjects).reduce((a, b) => a + b, 0); + return sum + dailySum; + }, 0); + + const totalEvaluated = domainData.reduce((sum, domain) => sum + domain.evaluated, 0); + const totalPartiallyEvaluated = domainData.reduce((sum, domain) => sum + domain.partiallyEvaluated, 0); + const totalCompletelyEvaluated = domainData.reduce((sum, domain) => sum + domain.completelyEvaluated, 0); + const totalJudges = domainData.reduce((sum, domain) => sum + domain.judges, 0); + + return ( +
+ {/* KPI Cards Row */} +
+
+
+
+

Total Allocated Projects

+

{totalProjectsAllocated}

+
+ +
+
+ +
+
+
+

Evaluated Projects

+

{totalEvaluated}

+
+ +
+
+ +
+
+
+

Partially Evaluated

+

{totalPartiallyEvaluated}

+
+ +
+
+ +
+
+
+

Completely Evaluated

+

{totalCompletelyEvaluated}

+
+ +
+
+ +
+
+
+

Total Judges (All Domains)

+

{totalJudges}

+
+ +
+
+
+ + {/* Charts Section: Bar Chart for Daily Allocated Projects */} +
+
+

Daily Allocated Projects (Per Domain)

+ + + + + + + + {domainData.map((domain, idx) => ( + + ))} + + +

Daily projects allocated across domains (last 6 days)

+
+ + {/* Evaluation Status Stacked Bar */} +
+

Evaluation Summary: Evaluated / Partially / Completely

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

Horizontal stacked view: total evaluated projects breakdown per domain

+
+
+ + {/* Domain-wise Judges Cards */} +
+

Judges per Domain

+
+ {domainData.map((domain, idx) => ( +
+ +

{domain.domain}

+

{domain.judges}

+

Active Judges

+
+ ))} +
+
+ + {/* Geographic Analytics: Cards + Pie Charts */} +
+ {/* Maharashtra vs Outside Maharashtra Card + Pie */} +
+

Maharashtra Origin

+
+
+

Outside Maharashtra

+

{geographicData.outsideMaharashtra}

+
+
+

From Maharashtra

+

{geographicData.fromMaharashtra}

+
+
+
+ + + `${name}: ${(percent * 100).toFixed(0)}%`}> + {locationTypeData.map((entry, index) => ( + + ))} + + + + +
+

Intern/participant distribution by Maharashtra state

+
+ + {/* International vs National Card */} +
+

International vs National

+
+
+

International

+

{geographicData.international}

+
+
+

National

+

{geographicData.national}

+
+
+
+ + + `${name}: ${(percent * 100).toFixed(0)}%`}> + {scopeData.map((entry, index) => ( + + ))} + + + + +
+

Scope: International participants vs National participants

+
+ + {/* Within Pune vs Outside Pune Card */} +
+

Pune Region Distribution

+
+
+

Within Pune

+

{geographicData.withinPune}

+
+
+

Outside Pune

+

{geographicData.outsidePune}

+
+
+
+ + + `${name}: ${(percent * 100).toFixed(0)}%`}> + {puneData.map((entry, index) => ( + + ))} + + + + +
+

Based on intern / participant location (Pune district)

+
+
+ + {/* Additional Summary Cards for quick stats */} +
+
+ +
+

Total Domain Categories

+

{domainData.length}

+
+
+
+ +
+

Avg. Completion Rate

+

{Math.round((totalCompletelyEvaluated / (totalEvaluated || 1)) * 100)}%

+
+
+
+ +
+

Judges to Projects Ratio

+

{(totalProjectsAllocated / totalJudges).toFixed(1)}

+
+
+
+ + {/* Detailed Domain Table (extra info) */} +
+
+

Domain-wise Detailed Metrics

+
+
+ + + + + + + + + + + + + {domainData.map((domain) => { + const totalAllocatedDomain = Object.values(domain.dailyProjects).reduce((a, b) => a + b, 0); + return ( + + + + + + + + + ); + })} + +
DomainTotal Allocated (Last 6d)EvaluatedPartially Eval.Completely Eval.Judges Count
{domain.domain}{totalAllocatedDomain}{domain.evaluated}{domain.partiallyEvaluated}{domain.completelyEvaluated}{domain.judges}
+
+
+
+ ); +}; + +// Main Dashboard Component with Tabs +const Dashboard = () => { + const [activeTab, setActiveTab] = useState('impeteus'); + + // You can use different data for each tab if needed + // For now, both tabs show the same data + const impeteusData = { + domainData: initialDomainData, + geographicData: geographicData + }; + + const conceptsData = { + domainData: initialDomainData, + geographicData: geographicData + }; + + return ( +
+ {/* Header */} +
+

📊 Project Evaluation Analytics Dashboard

+

Domain-wise tracking | Judge metrics | Geographic insights

+
+ + {/* Tab Navigation */} +
+
+ + +
+
+ + {/* Tab Content */} +
+ {activeTab === 'impeteus' && ( +
+
+

Impeteus Track - Project evaluation and judge analytics

+
+ +
+ )} + + {activeTab === 'concepts' && ( +
+
+

Concepts Track - Project evaluation and judge analytics

+
+ +
+ )} +
+ +
+

Analytics Dashboard — Real-time domain insights | Project evaluation status | Geographic segmentation (Maharashtra, Pune, National/International)

+
+
+ ); +}; + +export default Dashboard; \ No newline at end of file diff --git a/src/components/admin/ProjectJudgeAllocation.jsx b/src/components/admin/ProjectJudgeAllocation.jsx new file mode 100644 index 0000000..47f577d --- /dev/null +++ b/src/components/admin/ProjectJudgeAllocation.jsx @@ -0,0 +1,372 @@ +import { useEffect, useState, useMemo } from 'react'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { Chip, Box, Typography, CircularProgress, Alert } from '@mui/material'; +import { API_BASE } from '../../app/config/api'; + + +const ProjectJudgesAllocation = () => { + const [activeTab, setActiveTab] = useState('impetus'); + const [projects, setProjects] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + // All Filters + const [selectedDate, setSelectedDate] = useState(''); + const [domainFilter, setDomainFilter] = useState(''); + const [modeFilter, setModeFilter] = useState(''); // New: 'Online' | 'Offline' | 'Hybrid' | '' + const [statusFilter, setStatusFilter] = useState(null); // 'complete' | 'partial' | 'incomplete' | 'pending' + const [judgeCountFilter, setJudgeCountFilter] = useState(null); + const [paginationModel, setPaginationModel] = useState({ page: 0, pageSize: 10 }); + + // Domain mapping + const domainOptions = { + AD: 'APPLICATION DEVELOPMENT', + CN: 'COMMUNICATION NETWORKS AND SECURITY SYSTEMS', + DS: 'DIGITAL / IMAGE/ SPEECH / VIDEO PROCESSING', + ES: 'EMBEDDED/VLSI SYSTEMS', + ML: 'MACHINE LEARNING AND PATTERN RECOGNITION', + OT: 'OTHERS', + }; + + const getDomain = (pid) => { + if (typeof pid !== 'string') return 'OT'; + const match = pid.match(/-([A-Z]{2})/); + return match ? match[1] : 'OT'; + }; + + // Fetch data + useEffect(() => { + const fetchProjects = async () => { + setLoading(true); + setError(null); + try { + const response = await fetch(`${API_BASE}/view/admin/project-allocations?event=${activeTab}`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include', +}); + // const response = await fetch(`http://localhost:3001/view/admin/project-allocations?event=${activeTab}`); + if (!response.ok) throw new Error('Failed to fetch data'); + const data = await response.json(); + if (data.success) { + setProjects(data.projects || []); + } else { + throw new Error(data.message || 'Failed to load projects'); + } + } catch (err) { + console.error('Fetch error:', err); + setError(err.message || 'Something went wrong'); + setProjects([]); + } finally { + setLoading(false); + } + }; + fetchProjects(); + }, [activeTab]); + + const getEvaluationStatus = (project) => { + const judges = project.judges || []; + const allocated = judges.length; + const evaluated = judges.filter((j) => j?.evaluated === true).length; + if (allocated === 0) return 'pending'; + if (allocated >= 2 && evaluated >= 2) return 'complete'; + if (evaluated >= 1) return 'partial'; + return 'incomplete'; + }; + + const maxJudges = useMemo(() => { + return Math.max(4, ...projects.map((p) => (p.judges || []).length)); + }, [projects]); + + // Main filtered projects — ALL filters applied together + const filteredProjects = useMemo(() => { + return projects.filter((project) => { + // Date filter + if (selectedDate) { + const projectDateStr = project.date + ? new Date(project.date).toISOString().split('T')[0] + : null; + if (projectDateStr !== selectedDate) return false; + } + + // Domain filter + if (domainFilter && getDomain(project.pid) !== domainFilter) return false; + + // Mode filter + if (modeFilter && project.mode !== modeFilter) return false; + + // Judge count filter + if (judgeCountFilter !== null) { + const allocated = (project.judges || []).length; + if (allocated !== judgeCountFilter) return false; + } + + // Status filter + if (statusFilter) { + if (getEvaluationStatus(project) !== statusFilter) return false; + } + + return true; + }); + }, [projects, selectedDate, domainFilter, modeFilter, judgeCountFilter, statusFilter]); + + // Summary counts (based on filteredProjects so cards reflect all filters) + const domainCounts = useMemo(() => { + const counts = {}; + Object.keys(domainOptions).forEach((key) => (counts[key] = 0)); + filteredProjects.forEach((project) => { + const domain = getDomain(project.pid); + counts[domain] = (counts[domain] || 0) + 1; + }); + return counts; + }, [filteredProjects, domainOptions]); + + const statusCounts = useMemo(() => { + const counts = { complete: 0, partial: 0, incomplete: 0, pending: 0 }; + filteredProjects.forEach((project) => { + const status = getEvaluationStatus(project); + counts[status] = (counts[status] || 0) + 1; + }); + return counts; + }, [filteredProjects]); + + // Online / Offline totals (always full data) + const onlineTotal = useMemo(() => projects.filter((p) => p.mode === 'Online').length, [projects]); + const offlineTotal = useMemo(() => projects.filter((p) => p.mode === 'Offline').length, [projects]); + + // Rows for DataGrid + const rows = useMemo(() => { + return filteredProjects.map((project, index) => { + const judgesList = [...(project.judges || [])]; + while (judgesList.length < maxJudges) judgesList.push(null); + const dynamicJudges = {}; + judgesList.forEach((judge, i) => { + dynamicJudges[`judge${i + 1}`] = judge; + }); + return { + id: index, + pid: project.pid, + title: project.title, + session: project.session || 'N/A', + mode: project.mode || 'Offline', + date: project.date || null, + ...dynamicJudges, + }; + }); + }, [filteredProjects, maxJudges]); + + const renderJudgeCard = (judge) => { + if (!judge) { + return ( + + Slot Available + + ); + } + return ( + + + {judge.jid} + + + {judge.name} + + ); + }; + + const judgeColumns = useMemo(() => { + return Array.from({ length: maxJudges }, (_, i) => ({ + field: `judge${i + 1}`, + headerName: `Judge ${i + 1}`, + width: 220, + sortable: false, + flex: i === maxJudges - 1 ? 1 : 0, + renderCell: (params) => renderJudgeCard(params.value), + })); + }, [maxJudges]); + + const columns = [ + { field: 'pid', headerName: 'PID', width: 100, renderCell: (params) => {params.value} }, + { field: 'title', headerName: 'Project Title', width: 280, renderCell: (params) => {params.value} }, + { field: 'session', headerName: 'Session / Lab', width: 140 }, + { + field: 'mode', + headerName: 'Mode', + width: 110, + renderCell: (params) => ( + + ), + }, + { + field: 'date', + headerName: 'Date', + width: 130, + renderCell: (params) => ( + + {params.value ? new Date(params.value).toLocaleDateString('en-IN', { year: 'numeric', month: 'short', day: 'numeric' }) : '—'} + + ), + }, + ...judgeColumns, + ]; + + return ( +
+
+

Project Judges Allocation

+ + {/* Tabs */} +
+
+ + +
+
+ + {error && {error}} + + {/* Top Summary Cards: Online + Offline + Domain-wise */} +
+
+
ONLINE
+
{onlineTotal}
+
+
+
OFFLINE
+
{offlineTotal}
+
+ {Object.entries(domainOptions).map(([key, name]) => { + const count = domainCounts[key] || 0; + const isActive = domainFilter === key; + return ( +
setDomainFilter(isActive ? '' : key)} + className={`cursor-pointer bg-zinc-900 border transition-all hover:scale-105 rounded-3xl p-4 text-center ${isActive ? 'border-white shadow-2xl' : 'border-zinc-700'}`} + > +
{key}
+
{count}
+
{name}
+
+ ); + })} +
+ + {/* Filters Row */} +
+ {/* Date Filter */} +
+ Date: + setSelectedDate(e.target.value)} className="bg-zinc-900 border border-zinc-700 focus:border-blue-500 rounded-2xl px-5 py-3 text-white outline-none w-52" /> + {selectedDate && } +
+ + {/* Domain Dropdown */} +
+ Domain: + + {domainFilter && } +
+ + {/* Mode Filter */} +
+ Mode: + + {modeFilter && } +
+
+ + {/* Status Cards */} +
+ {[ + { key: 'complete', label: 'Completely Evaluated', color: 'emerald' }, + { key: 'partial', label: 'Partially Evaluated', color: 'amber' }, + { key: 'incomplete', label: 'Not Evaluated', color: 'red' }, + { key: 'pending', label: 'Not Assigned', color: 'zinc' }, + ].map(({ key, label, color }) => { + const count = statusCounts[key] || 0; + const isActive = statusFilter === key; + return ( +
setStatusFilter(isActive ? null : key)} + className={`cursor-pointer bg-zinc-900 border transition-all hover:scale-105 rounded-3xl p-6 ${isActive ? 'border-white shadow-2xl' : 'border-zinc-700'}`} + > +
{label.toUpperCase()}
+
{count}
+
+ ); + })} +
+ + {/* Judge Count Filter */} +
+ Judges Allocated: + {[null, 0, 1, 2, 3, 4, 5, 6, 7].map((num) => { + const label = num === null ? 'All' : num; + const isActive = judgeCountFilter === num; + return ( + + ); + })} +
+ + {/* DataGrid */} +
+ 130} + sx={{ + border: 'none', + '& .MuiDataGrid-cell': { color: '#e2e8f0', fontSize: '0.9rem', borderRight: '1px solid #3f3f46', padding: '8px 12px' }, + '& .MuiDataGrid-columnHeader': { backgroundColor: '#18181b', color: '#a1a1aa', fontWeight: 600, fontSize: '0.9rem' }, + '& .MuiDataGrid-row:hover': { backgroundColor: '#27272a' }, + '& .MuiDataGrid-toolbarContainer': { backgroundColor: '#18181b', color: '#e2e8f0' }, + '& .MuiDataGrid-footerContainer': { color: '#e2e8f0', backgroundColor: '#18181b', borderTop: '1px solid #3f3f46' }, + '& .MuiTablePagination-root, & .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows': { color: '#e2e8f0' }, + '& .MuiIconButton-root': { color: '#e2e8f0' }, + }} + /> +
+ + {loading && ( + + + + )} +
+
+ ); +}; + +export default ProjectJudgesAllocation; \ No newline at end of file diff --git a/src/components/admin/ProjectReallocate.jsx b/src/components/admin/ProjectReallocate.jsx new file mode 100644 index 0000000..55033a2 --- /dev/null +++ b/src/components/admin/ProjectReallocate.jsx @@ -0,0 +1,333 @@ +import { useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Search, UserPlus, RefreshCw, Info, CheckCircle2 } from 'lucide-react'; +import { API_BASE } from '../../app/config/api'; + +const API_BASE_M= `${API_BASE}/view/admin`; // ← Change to your actual backend URL + +const ProjectReallocate = () => { + const [searchPid, setSearchPid] = useState(""); + const [hasSearched, setHasSearched] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const [problem, setProblem] = useState(null); + const [allocatedJudges, setAllocatedJudges] = useState([]); + const [availableJudges, setAvailableJudges] = useState([]); + const [selectedJudgeId, setSelectedJudgeId] = useState(null); + const [reallocationHistory, setReallocationHistory] = useState([]); + const [poolSearch, setPoolSearch] = useState(""); + // const [isEditingLab, setIsEditingLab] = useState(false); // COMMENTED: Lab editing state removed + // const [saveSuccess, setSaveSuccess] = useState(false); // COMMENTED: Lab save success state removed + const [reallocateSuccess, setReallocateSuccess] = useState(false); + + // Filter available judges + const filteredAvailableJudges = availableJudges.filter((judge) => { + const query = poolSearch.trim().toLowerCase(); + if (!query) return true; + return ( + judge.id.toLowerCase().includes(query) || + judge.name.toLowerCase().includes(query) || + judge.expertise.toLowerCase().includes(query) + ); + }); + + // Fetch project data + const fetchProject = async (pid) => { + setLoading(true); + setError(""); + try { + // const res = await fetch(`${API_BASE_M}/project-reallocation/${pid}`); + const res = await fetch(`${API_BASE_M}/project-reallocation/${pid}`, { + headers: { 'Content-Type': 'application/json' }, + method: 'GET', + credentials: 'include' +}); + const data = await res.json(); + + if (!data.success) { + throw new Error(data.message || "Failed to fetch project"); + } + + setProblem({ + pid: data.project.pid, + title: data.project.title, + domain: data.project.domain, + description: data.project.description, + + // ==================== LAB SESSION HANDLING - COMMENTED OUT ==================== + // We store date and time separately for easy editing + // labDate: data.project.lab ? data.project.lab.split(' ')[0] : "2026-04-15", + // labTime: data.project.lab + // ? data.project.lab.split(' ').slice(1).join(' ').trim() + // : "10:00", + // ============================================================= + }); + + setAllocatedJudges(data.allocatedJudges.map(j => ({ + id: j.id, + name: j.name, + expertise: j.expertise, + evaluated: j.evaluated || false + }))); + + setAvailableJudges(data.availableJudges.map(j => ({ + id: j.id, + name: j.name, + expertise: j.expertise + }))); + + setHasSearched(true); + setReallocationHistory([]); + } catch (err) { + setError(err.message); + setHasSearched(false); + } finally { + setLoading(false); + } + }; + + const handleSearch = (e) => { + e.preventDefault(); + const trimmed = searchPid.trim().toUpperCase(); + if (trimmed) { + fetchProject(trimmed); + } + }; + + const handleSelectToReplace = (id) => { + setSelectedJudgeId(prev => prev === id ? null : id); + }; + + const handleSwap = async (newJudge) => { + if (!selectedJudgeId || !problem) return; + + const oldJudge = allocatedJudges.find(j => j.id === selectedJudgeId); + if (!oldJudge) return; + + try { + const res = await fetch(`${API_BASE_M}/reallocate-judge`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include' , + body: JSON.stringify({ + pid: problem.pid, + oldJid: oldJudge.id, + newJid: newJudge.id + }) + }); + + const data = await res.json(); + + if (!data.success) { + alert(data.message || "Reallocation failed"); + return; + } + + setAllocatedJudges(prev => + prev.map(j => j.id === selectedJudgeId ? { ...newJudge, evaluated: false } : j) + ); + + setAvailableJudges(prev => { + const filtered = prev.filter(j => j.id !== newJudge.id); + return [...filtered, { ...oldJudge }]; + }); + + const now = new Date(); + setReallocationHistory(prev => [...prev, { + from: oldJudge.name, + to: newJudge.name, + date: now.toISOString().split('T')[0], + timestamp: now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) + }]); + + setSelectedJudgeId(null); + setReallocateSuccess(true); + setTimeout(() => setReallocateSuccess(false), 2500); + + } catch (err) { + console.error(err); + alert("Network error during reallocation"); + } + }; + + return ( +
+
+ + {/* Header & Search */} +
+

+ Judge Reallocation Dashboard +

+ +
+
+ + setSearchPid(e.target.value)} + placeholder="Enter PID (e.g. IM123 or C456)" + className="block w-full pl-10 pr-4 py-3 bg-white/5 border border-white/10 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500/50 text-white placeholder-gray-500" + /> +
+ +
+ + {error &&

{error}

} +
+ + + {hasSearched && problem && ( + + {/* Problem Details - Lab Session Section REMOVED */} +
+
+
+
+ {problem.pid} +
+ +

{problem.title}

+

{problem.domain}

+

{problem.description}

+ + {/* ==================== LAB SESSION EDITING SECTION - COMPLETELY REMOVED ==================== */} + {/* The entire Lab Session UI block has been removed */} + {/* ================================================================== */} + +
+ +
+ +
+
+
+ + {/* Reallocation Grid - Same as before */} +
+ {/* Allocated Judges Column */} +
+

+ Allocated Judges {allocatedJudges.length} +

+
+ {allocatedJudges.map((judge) => { + const isSelected = selectedJudgeId === judge.id; + return ( + +
+
+

{judge.id}

+

{judge.name}

+

{judge.expertise}

+ {judge.evaluated &&

✓ Already Evaluated

} +
+ +
+
+ ); + })} +
+
+ + {/* Available Pool Column */} +
+
+

+ Available Judges Pool {filteredAvailableJudges.length} +

+ {selectedJudgeId &&

Select a judge above to assign

} +
+ +
+ + setPoolSearch(e.target.value)} + placeholder="Search by ID, name or expertise..." + className="w-full pl-11 pr-4 py-3 bg-white/5 border border-white/10 rounded-xl focus:ring-2 focus:ring-blue-500 text-white" + /> +
+ +
+ {filteredAvailableJudges.map((judge) => ( + +
+
+

{judge.id}

+

{judge.name}

+

{judge.expertise}

+
+ +
+
+ ))} +
+
+
+ + {/* Reallocation History */} + {reallocationHistory.length > 0 && ( +
+

Reallocation History

+
+ {reallocationHistory.map((entry, i) => ( +
+
+ {entry.from} + + {entry.to} +
+
{entry.date} • {entry.timestamp}
+
+ ))} +
+
+ )} + + + {reallocateSuccess && ( + + Judge reallocated successfully! + + )} + +
+ )} +
+
+ + +
+ ); +}; + +export default ProjectReallocate; \ No newline at end of file diff --git a/src/components/admin/ProjectSchedule.jsx b/src/components/admin/ProjectSchedule.jsx new file mode 100644 index 0000000..a84eeb2 --- /dev/null +++ b/src/components/admin/ProjectSchedule.jsx @@ -0,0 +1,325 @@ +import { useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Search, Info, CalendarDays, Clock4, MapPin, UserRound, Loader2, ChevronDown } from 'lucide-react'; +import { API_BASE } from '../../app/config/api'; + +const API_BASE_M = `${API_BASE}/view/admin`; + +const slotMeta = { + 1: { room: 'Lab A-201', coordinator: 'Prof. Priya Kulkarni' }, + 2: { room: 'Lab A-203', coordinator: 'Prof. Nitin Deshmukh' }, + 3: { room: 'Lab B-102', coordinator: 'Dr. Kavya Patil' }, + 4: { room: 'Lab B-205', coordinator: 'Prof. Ashutosh More' }, + 5: { room: 'Lab C-101', coordinator: 'Dr. Meera Shah' }, + 6: { room: 'Lab C-204', coordinator: 'Prof. Rohan Joshi' }, +}; + +const ScheduleCard = ({ slotLabel, room, coordinator, projectId }) => { + return ( +
+
+

+ + {slotLabel} +

+

+ + {room} +

+

+ + Coordinator: {coordinator} +

+
+ Project: {projectId} +
+
+
+ ); +}; + +const AdminJudgingSchedule = () => { + const [pid, setPid] = useState(''); + const [hasSearched, setHasSearched] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + // Data from API + const [projectData, setProjectData] = useState(null); + const [assignedSlots, setAssignedSlots] = useState([]); + const [judgingSlots, setJudgingSlots] = useState({}); + const [eventName, setEventName] = useState('impetus'); + + // For collapsible abstract + const [showAbstract, setShowAbstract] = useState(false); + + const handleSearch = async (e) => { + e.preventDefault(); + const trimmedPid = pid.trim().toUpperCase(); + + if (!trimmedPid) { + setError('Please enter a Project ID'); + return; + } + + setLoading(true); + setError(''); + setHasSearched(false); + setShowAbstract(false); // Reset abstract visibility on new search + + try { + const response = await fetch(`${API_BASE_M}/project-schedule/${trimmedPid}`, { + method: 'GET', // explicitly a GET request + headers: { + 'Content-Type': 'application/json' // optional for GET + }, + credentials: 'include' // include cookies/session if needed +}); + + + if (!response.ok) { + if (response.status === 404) throw new Error('Project not found'); + throw new Error('Failed to fetch project schedule'); + } + + const result = await response.json(); + + if (!result.success) { + throw new Error(result.message || 'Something went wrong'); + } + + // Update state with real data + setProjectData(result.project); + setAssignedSlots(result.assignedSlots || []); + setJudgingSlots(result.judgingSlots || {}); + setEventName(result.event || 'impetus'); + setHasSearched(true); + + } catch (err) { + console.error(err); + setError(err.message); + setHasSearched(false); + } finally { + setLoading(false); + } + }; + + // Group slots by day + const groupedAllSlots = Object.entries(judgingSlots).reduce((acc, [slotId, slotLabel]) => { + const dayKey = slotLabel.split('(')[0].trim(); + if (!acc[dayKey]) acc[dayKey] = []; + acc[dayKey].push({ + slotId, + slotLabel, + isAssigned: assignedSlots.includes(slotId) + }); + return acc; + }, {}); + + // Sort slots within each day + Object.values(groupedAllSlots).forEach((slots) => { + slots.sort((a, b) => Number(a.slotId) - Number(b.slotId)); + }); + + const orderedDayLabels = Object.keys(groupedAllSlots); + + return ( +
+
+
+
+

+ Schedule Dashboard +

+

+ Search by Problem ID to view day-wise project schedule with time slots, lab allocation, and coordinator details. +

+
+ +
+ + +
+ +
+
+
+ +
+ setPid(e.target.value)} + placeholder="Enter PID (e.g. IM-1234 or P-1042)" + className="block w-full pl-10 pr-3 py-3 border border-white/10 rounded-xl bg-white/5 backdrop-blur-md text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-transparent transition-all duration-300" + disabled={loading} + /> +
+ +
+ + {error && ( +
+ {error} +
+ )} +
+ + + {hasSearched && projectData && ( + + {/* Project Info Card with Collapsible Abstract */} +
+
+ +
+
+ + {projectData.pid} +
+ +

+ {projectData.title} +

+ +

{projectData.domain}

+ + {/* Collapsible Abstract Section */} +
+ + + + {showAbstract && ( + + {projectData.description} + + )} + +
+ + {/* Project Details */} +
+

Lab: {projectData.lab}

+

Coordinator: {projectData.coordinator}

+

Mode: {projectData.mode}

+
+
+
+ + {/* Day-wise Schedule */} +
+
+ + Day-wise Judging Schedule ({eventName.charAt(0).toUpperCase() + eventName.slice(1)}) +
+ +
+ {[1, 2, 3].map((dayNumber) => { + const dayLabel = orderedDayLabels[dayNumber - 1]; + const slots = dayLabel ? groupedAllSlots[dayLabel] : []; + + return ( +
+

+ {`Day ${dayNumber}${dayLabel ? ` - ${dayLabel}` : ''}`} +

+ + {slots.length > 0 ? ( +
+ {slots.map(({ slotId, slotLabel, isAssigned }) => + isAssigned ? ( + + ) : ( +
+ Slot not assigned for this project +
+ ) + )} +
+ ) : ( +
+ No slot data available for this day. +
+ )} +
+ ); + })} +
+
+
+ )} +
+ + {!hasSearched && !loading && ( +
+
+ +
+
+

No problem selected

+

+ Use the search bar above to view schedule details for a specific PID. +

+
+
+ )} +
+
+ ); +}; + +export default AdminJudgingSchedule; \ No newline at end of file diff --git a/src/components/navbar.jsx b/src/components/navbar.jsx index 3c9c88b..337b301 100644 --- a/src/components/navbar.jsx +++ b/src/components/navbar.jsx @@ -104,7 +104,13 @@ const Navbar = () => { :
  • {setActive(link.title); setToggle(!toggle);}}> { - {link.title} + // {link.title} + + + {link.title} + }
  • ))} diff --git a/src/constants/index.js b/src/constants/index.js index cf52e0f..9df3a5c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -25,7 +25,8 @@ export const navItems = [ { id: "about", title: "About", type: "hash" }, { id: "events", title: "Events", type: "hash" }, { id: "committee", title: "Committee", type: "route", path: "/committee/core" }, - { id: "register", title: "Register", type: "route", path: "/register" } + { id: "register", title: "Register", type: "route", path: "/register" }, + { id: "schedule", title: "Schedule", type: "route", path: "/schedule" } ]; @@ -52,6 +53,11 @@ export const navItems = [ // isHome: false, // title: "Committee", // }, + { + id: "schedule", + isHome: false, + title: "Schedule", + }, { id: "register", isHome: false, @@ -95,6 +101,26 @@ export const navItems = [ isHome: false, title: "Results", }, + { + id: "admin/view/allocation", + isHome: false, + title: "View Allocations", + }, + { + id: "admin/view/project-judge", + isHome: false, + title: "Project Judges", + }, + // { + // id: "admin/view/analytics", + // isHome: false, + // title: "Analytics", + // }, + { + id: "admin/reallocate", + isHome: false, + title: "Reallocate", + }, { id: "admin/logout", isHome: false, From d3de1367df490313ce902f7570bcb2df3cf15750 Mon Sep 17 00:00:00 2001 From: KALYANI100 Date: Thu, 26 Mar 2026 15:15:58 +0530 Subject: [PATCH 2/2] lint-resolve --- package-lock.json | 50 ++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/package-lock.json b/package-lock.json index 178f3df..c5dacfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -97,7 +97,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -420,7 +419,6 @@ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -464,7 +462,6 @@ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1396,6 +1393,7 @@ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.8.tgz", "integrity": "sha512-du5dlPZ9XL3xW2apHoGDXBI+QLtyVJGrXNCfcNYfP/ojkz1RQ0rRV6VG9Rkm1DqEFRG8mjjTL7zmE1Bvn1eR4A==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "@mui/utils": "^7.3.8", @@ -1423,6 +1421,7 @@ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.11.tgz", "integrity": "sha512-fZ2xO9D08IKOxO2oUBi1nnVKH6oJUD+64cnv4YAaFoC0E5+i1+S5AHbNqqvZlYYsbPEQ6qEVwuBqY3jl5W4G+Q==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6" }, @@ -1440,6 +1439,7 @@ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.8.tgz", "integrity": "sha512-kZRcE2620CBGr+XI8YMmwPj6WIPwSF7uMJjvSfqd8zXVvlz0MCJbzRRUGNf8NgflCLthdji2DdS643TeyJ3+nA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "@mui/types": "^7.4.11", @@ -1470,6 +1470,7 @@ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.8.tgz", "integrity": "sha512-JHAeXQzS0tJ+Fq3C6J4TVDsW+yKhO4uuxuiLaopNStJeQYBIUCXpKYyUCcgXym4AmhbznQnv9RlHywSH6b0FOg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "@emotion/cache": "^11.14.0", @@ -1504,6 +1505,7 @@ "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.8.tgz", "integrity": "sha512-hoFRj4Zw2Km8DPWZp/nKG+ao5Jw5LSk2m/e4EGc6M3RRwXKEkMSG4TgtfVJg7dS2homRwtdXSMW+iRO0ZJ4+IA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "@mui/private-theming": "^7.3.8", @@ -1544,6 +1546,7 @@ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.11.tgz", "integrity": "sha512-fZ2xO9D08IKOxO2oUBi1nnVKH6oJUD+64cnv4YAaFoC0E5+i1+S5AHbNqqvZlYYsbPEQ6qEVwuBqY3jl5W4G+Q==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6" }, @@ -1561,6 +1564,7 @@ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.8.tgz", "integrity": "sha512-kZRcE2620CBGr+XI8YMmwPj6WIPwSF7uMJjvSfqd8zXVvlz0MCJbzRRUGNf8NgflCLthdji2DdS643TeyJ3+nA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "@mui/types": "^7.4.11", @@ -1934,7 +1938,6 @@ "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.18.0.tgz", "integrity": "sha512-FYZZqD0UUHUswKz3LQl2Z7H24AhD14XGTsIRw3SJaXUxyfVMi+1yiZGmqTcPt/CkPpdU7rrxqcyQ1zJE5DjvIQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.26.7", @@ -2559,12 +2562,6 @@ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, - "node_modules/@types/debounce": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.4.tgz", - "integrity": "sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==", - "license": "MIT" - }, "node_modules/@types/draco3d": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", @@ -2608,7 +2605,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -2620,7 +2616,6 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -2654,7 +2649,6 @@ "resolved": "https://registry.npmjs.org/@types/three/-/three-0.183.1.tgz", "integrity": "sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw==", "license": "MIT", - "peer": true, "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", @@ -2728,7 +2722,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3145,7 +3138,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3315,7 +3307,6 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", - "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -4083,7 +4074,6 @@ "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4873,7 +4863,6 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz", "integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -5403,7 +5392,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -6126,7 +6114,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -6232,7 +6219,6 @@ "resolved": "https://registry.npmjs.org/postprocessing/-/postprocessing-6.38.3.tgz", "integrity": "sha512-5qCFp8j62nWL6sSVv/RKuHscQUIV+VMMgWeHLYZQEBpAk7G+r3jA3bSKON7gZjiuxdZ/F4PXj2Jc1oPh/7Eg+g==", "license": "Zlib", - "peer": true, "peerDependencies": { "three": ">= 0.157.0 < 0.184.0" } @@ -6316,7 +6302,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -6351,7 +6336,6 @@ "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" @@ -6413,7 +6397,6 @@ "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", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -6577,12 +6560,21 @@ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/recharts/node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "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", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -7338,8 +7330,7 @@ "version": "0.172.0", "resolved": "https://registry.npmjs.org/three/-/three-0.172.0.tgz", "integrity": "sha512-6HMgMlzU97MsV7D/tY8Va38b83kz8YJX+BefKjspMNAv0Vx6dxMogHOrnRl/sbMIs3BPUKijPqDqJ/+UwJbIow==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/three-mesh-bvh": { "version": "0.7.8", @@ -7421,7 +7412,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -7726,7 +7716,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -7820,7 +7809,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" },