diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json
index a187d1e..69b0f17 100644
--- a/Frontend/package-lock.json
+++ b/Frontend/package-lock.json
@@ -13,11 +13,13 @@
"@types/react-redux": "^7.1.31",
"antd": "^5.11.3",
"axios": "^1.6.2",
+ "dayjs": "^1.11.10",
"next": "14.0.0",
"react": "^18",
"react-dom": "^18",
"react-icons": "^4.12.0",
- "react-redux": "^8.1.3"
+ "react-redux": "^8.1.3",
+ "recharts": "^2.10.3"
},
"devDependencies": {
"@types/node": "^20",
@@ -616,6 +618,60 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
+ },
+ "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=="
+ },
+ "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=="
+ },
+ "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==",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.2.tgz",
+ "integrity": "sha512-WAIEVlOCdd/NKRYTsqCpOMHQHemKBEINf8YXMYOtXH0GA7SY0dqMB78P3Uhgfy+4X+/Mlw2wDtlETkN6kQUCMA=="
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+ "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+ "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
+ "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
+ },
+ "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=="
+ },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
@@ -1390,6 +1446,14 @@
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
+ "node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1478,6 +1542,116 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
+ "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==",
+ "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==",
+ "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==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "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==",
+ "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==",
+ "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==",
+ "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==",
+ "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==",
+ "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==",
+ "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==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -1506,6 +1680,11 @@
}
}
},
+ "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=="
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -1596,6 +1775,14 @@
"node": ">=6.0.0"
}
},
+ "node_modules/dom-helpers": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
+ "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.601",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz",
@@ -2167,12 +2354,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ },
"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
},
+ "node_modules/fast-equals": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@@ -2707,6 +2907,14 @@
"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==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/is-array-buffer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
@@ -3207,6 +3415,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -3438,7 +3651,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3865,7 +4077,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -4525,6 +4736,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
"node_modules/react-redux": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
@@ -4568,6 +4784,35 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
+ "node_modules/react-smooth": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.5.tgz",
+ "integrity": "sha512-BMP2Ad42tD60h0JW6BFaib+RJuV5dsXJK9Baxiv/HlNFjvRLqA9xrNKxVWnUIZPQfzUwGXIlU/dSYLU+54YGQA==",
+ "dependencies": {
+ "fast-equals": "^5.0.0",
+ "react-transition-group": "2.9.0"
+ },
+ "peerDependencies": {
+ "prop-types": "^15.6.0",
+ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
+ "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
+ "dependencies": {
+ "dom-helpers": "^3.4.0",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2",
+ "react-lifecycles-compat": "^3.0.4"
+ },
+ "peerDependencies": {
+ "react": ">=15.0.0",
+ "react-dom": ">=15.0.0"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -4589,6 +4834,37 @@
"node": ">=8.10.0"
}
},
+ "node_modules/recharts": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.10.3.tgz",
+ "integrity": "sha512-G4J96fKTZdfFQd6aQnZjo2nVNdXhp+uuLb00+cBTGLo85pChvm1+E67K3wBOHDE/77spcYb2Cy9gYWVqiZvQCg==",
+ "dependencies": {
+ "clsx": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.19",
+ "react-is": "^16.10.2",
+ "react-smooth": "^2.0.5",
+ "recharts-scale": "^0.4.4",
+ "tiny-invariant": "^1.3.1",
+ "victory-vendor": "^36.6.8"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "prop-types": "^15.6.0",
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "dependencies": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
"node_modules/redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
@@ -5169,6 +5445,11 @@
"node": ">=12.22"
}
},
+ "node_modules/tiny-invariant": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz",
+ "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw=="
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -5397,6 +5678,27 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
+ "node_modules/victory-vendor": {
+ "version": "36.7.0",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz",
+ "integrity": "sha512-nqYuTkLSdTTeACyXcCLbL7rl0y6jpzLPtTNGOtSnajdR+xxMxBdjMxDjfNJNlhR+ZU8vbXz+QejntcbY7h9/ZA==",
+ "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/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
diff --git a/Frontend/package.json b/Frontend/package.json
index dfb4987..cb10f23 100644
--- a/Frontend/package.json
+++ b/Frontend/package.json
@@ -14,11 +14,13 @@
"@types/react-redux": "^7.1.31",
"antd": "^5.11.3",
"axios": "^1.6.2",
+ "dayjs": "^1.11.10",
"next": "14.0.0",
"react": "^18",
"react-dom": "^18",
"react-icons": "^4.12.0",
- "react-redux": "^8.1.3"
+ "react-redux": "^8.1.3",
+ "recharts": "^2.10.3"
},
"devDependencies": {
"@types/node": "^20",
diff --git a/Frontend/src/app/analytics/page.tsx b/Frontend/src/app/analytics/page.tsx
new file mode 100644
index 0000000..964e8bb
--- /dev/null
+++ b/Frontend/src/app/analytics/page.tsx
@@ -0,0 +1,10 @@
+"use client";
+import { AnalyticsContainer } from "@/containers";
+
+export default function Analytics() {
+ return (
+
+ );
+}
diff --git a/Frontend/src/components/card/card.tsx b/Frontend/src/components/card/card.tsx
new file mode 100644
index 0000000..5694710
--- /dev/null
+++ b/Frontend/src/components/card/card.tsx
@@ -0,0 +1,20 @@
+import { PropsWithChildren } from "react";
+
+type PropsType = {
+ header?: React.ReactNode;
+};
+
+/** This component renders a card*/
+export const Card: React.FC> = ({
+ children,
+ header,
+}) => {
+ return (
+
+
+ {header && <>{header}>}
+
+
{children}
+
+ );
+};
diff --git a/Frontend/src/components/index.ts b/Frontend/src/components/index.ts
index b866757..4d72aad 100644
--- a/Frontend/src/components/index.ts
+++ b/Frontend/src/components/index.ts
@@ -1,3 +1,4 @@
export { VideoRecordingScreen } from "./video-recording-screen/video-recording-screen";
export { Table } from "./table/table";
export { Button } from "./button/button";
+export { Card } from "./card/card";
diff --git a/Frontend/src/containers/about-us-mission-container.tsx b/Frontend/src/containers/about-us-container/about-us-mission-container.tsx
similarity index 100%
rename from Frontend/src/containers/about-us-mission-container.tsx
rename to Frontend/src/containers/about-us-container/about-us-mission-container.tsx
diff --git a/Frontend/src/containers/about-us-overview-container.tsx b/Frontend/src/containers/about-us-container/about-us-overview-container.tsx
similarity index 100%
rename from Frontend/src/containers/about-us-overview-container.tsx
rename to Frontend/src/containers/about-us-container/about-us-overview-container.tsx
diff --git a/Frontend/src/containers/about-us-solution-container.tsx b/Frontend/src/containers/about-us-container/about-us-solution-container.tsx
similarity index 100%
rename from Frontend/src/containers/about-us-solution-container.tsx
rename to Frontend/src/containers/about-us-container/about-us-solution-container.tsx
diff --git a/Frontend/src/containers/about-us-team-container.tsx b/Frontend/src/containers/about-us-container/about-us-team-container.tsx
similarity index 100%
rename from Frontend/src/containers/about-us-team-container.tsx
rename to Frontend/src/containers/about-us-container/about-us-team-container.tsx
diff --git a/Frontend/src/containers/analytics-container/analytics-container.tsx b/Frontend/src/containers/analytics-container/analytics-container.tsx
new file mode 100644
index 0000000..18ad429
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/analytics-container.tsx
@@ -0,0 +1,38 @@
+"use client";
+import type { FC } from "react";
+import React from "react";
+import { AuthorizedCounterContainer } from "./authorized-counter/authorized-counter";
+import { UnauthorizedCounterContainer } from "./unauthorized-counter/unauthorized-counter";
+import { AuthorizedUnauthorizedPieContainer } from "./authorized-unauthorized-pie/authorized-unauthorized-pie";
+import { AuthorizedUnauthorizedLineContainer } from "./authorized-unauthorized-line/authorized-unauthorized-line";
+import { UserAreaBarContainer } from "./user-area-bar/user-area-bar";
+import { RecentAuthorizedContainer } from "./recent-authorized/recent-authorized";
+import { RecentUnauthorizedContainer } from "./recent-unauthorized/recent-unauthorized";
+
+/* This container renders analytics sections */
+export const AnalyticsContainer: FC = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/authorized-counter/authorized-counter.tsx b/Frontend/src/containers/analytics-container/authorized-counter/authorized-counter.tsx
new file mode 100644
index 0000000..24a326c
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/authorized-counter/authorized-counter.tsx
@@ -0,0 +1,60 @@
+import React, { useState } from "react";
+import type { FC } from "react";
+import { SecurityScanOutlined } from "@ant-design/icons";
+import { Statistic, Select, DatePicker } from "antd";
+import { Card } from "@/components";
+import dayjs from "dayjs";
+import type { Dayjs } from "dayjs";
+import { theme } from "../../../../theme";
+
+export const AuthorizedCounterContainer: FC = () => {
+ const [timeOption, setTimeOption] = useState<"day" | "month">("day");
+ const [date, setDate] = useState(dayjs());
+
+ const CardHeader: FC = () => {
+ return (
+
+ Authorized access
+
+
+ );
+ };
+
+ return (
+ <>
+ }>
+ }
+ />
+
+
No of attempts on:
+
+
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/authorized-unauthorized-line/authorized-unauthorized-line.tsx b/Frontend/src/containers/analytics-container/authorized-unauthorized-line/authorized-unauthorized-line.tsx
new file mode 100644
index 0000000..ecc5cf8
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/authorized-unauthorized-line/authorized-unauthorized-line.tsx
@@ -0,0 +1,511 @@
+import React, { useState } from "react";
+import type { FC } from "react";
+import { Select, DatePicker } from "antd";
+import { Card } from "@/components";
+import dayjs from "dayjs";
+import type { Dayjs } from "dayjs";
+import { theme } from "../../../../theme";
+import {
+ LineChart,
+ Line,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+ ResponsiveContainer,
+ Label,
+} from "recharts";
+
+export const AuthorizedUnauthorizedLineContainer: FC = () => {
+ const [timeOption, setTimeOption] = useState<"day" | "month">("day");
+ const [date, setDate] = useState(dayjs());
+ const data01 = {
+ month: [
+ {
+ time: "1",
+ authorizedEntity: 291,
+ unauthorizedEntity: 925,
+ },
+ {
+ time: 2,
+ authorizedEntity: 630,
+ unauthorizedEntity: 825,
+ },
+ {
+ time: 3,
+ authorizedEntity: 156,
+ unauthorizedEntity: 43,
+ },
+ {
+ time: 4,
+ authorizedEntity: 87,
+ unauthorizedEntity: 588,
+ },
+ {
+ time: 5,
+ authorizedEntity: 456,
+ unauthorizedEntity: 244,
+ },
+ {
+ time: 6,
+ authorizedEntity: 814,
+ unauthorizedEntity: 694,
+ },
+ {
+ time: 7,
+ authorizedEntity: 266,
+ unauthorizedEntity: 267,
+ },
+ {
+ time: 8,
+ authorizedEntity: 280,
+ unauthorizedEntity: 76,
+ },
+ {
+ time: 9,
+ authorizedEntity: 584,
+ unauthorizedEntity: 441,
+ },
+ {
+ time: 10,
+ authorizedEntity: 65,
+ unauthorizedEntity: 793,
+ },
+ {
+ time: 11,
+ authorizedEntity: 870,
+ unauthorizedEntity: 30,
+ },
+ {
+ time: 12,
+ authorizedEntity: 362,
+ unauthorizedEntity: 207,
+ },
+ {
+ time: 13,
+ authorizedEntity: 384,
+ unauthorizedEntity: 827,
+ },
+ {
+ time: 14,
+ authorizedEntity: 359,
+ unauthorizedEntity: 663,
+ },
+ {
+ time: 15,
+ authorizedEntity: 706,
+ unauthorizedEntity: 878,
+ },
+ {
+ time: 16,
+ authorizedEntity: 362,
+ unauthorizedEntity: 512,
+ },
+ {
+ time: 17,
+ authorizedEntity: 958,
+ unauthorizedEntity: 876,
+ },
+ {
+ time: 18,
+ authorizedEntity: 501,
+ unauthorizedEntity: 676,
+ },
+ {
+ time: 19,
+ authorizedEntity: 188,
+ unauthorizedEntity: 48,
+ },
+ {
+ time: 20,
+ authorizedEntity: 502,
+ unauthorizedEntity: 166,
+ },
+ {
+ time: 21,
+ authorizedEntity: 496,
+ unauthorizedEntity: 905,
+ },
+ {
+ time: 22,
+ authorizedEntity: 342,
+ unauthorizedEntity: 830,
+ },
+ {
+ time: 23,
+ authorizedEntity: 554,
+ unauthorizedEntity: 569,
+ },
+ {
+ time: 24,
+ authorizedEntity: 894,
+ unauthorizedEntity: 78,
+ },
+ {
+ time: 25,
+ authorizedEntity: 276,
+ unauthorizedEntity: 767,
+ },
+ {
+ time: 26,
+ authorizedEntity: 760,
+ unauthorizedEntity: 61,
+ },
+ {
+ time: 27,
+ authorizedEntity: 451,
+ unauthorizedEntity: 174,
+ },
+ {
+ time: 28,
+ authorizedEntity: 568,
+ unauthorizedEntity: 994,
+ },
+ {
+ time: 29,
+ authorizedEntity: 954,
+ unauthorizedEntity: 799,
+ },
+ {
+ time: 30,
+ authorizedEntity: 463,
+ unauthorizedEntity: 560,
+ },
+ {
+ time: 31,
+ authorizedEntity: 744,
+ unauthorizedEntity: 207,
+ },
+ ],
+ day: [
+ {
+ time: "00:00",
+ authorizedEntity: 913,
+ unauthorizedEntity: 185,
+ },
+ {
+ time: "00:30",
+ authorizedEntity: 702,
+ unauthorizedEntity: 861,
+ },
+ {
+ time: "01:00",
+ authorizedEntity: 379,
+ unauthorizedEntity: 492,
+ },
+ {
+ time: "01:30",
+ authorizedEntity: 172,
+ unauthorizedEntity: 416,
+ },
+ {
+ time: "02:00",
+ authorizedEntity: 963,
+ unauthorizedEntity: 504,
+ },
+ {
+ time: "02:30",
+ authorizedEntity: 524,
+ unauthorizedEntity: 830,
+ },
+ {
+ time: "03:00",
+ authorizedEntity: 198,
+ unauthorizedEntity: 131,
+ },
+ {
+ time: "03:30",
+ authorizedEntity: 254,
+ unauthorizedEntity: 584,
+ },
+ {
+ time: "04:00",
+ authorizedEntity: 905,
+ unauthorizedEntity: 894,
+ },
+ {
+ time: "04:30",
+ authorizedEntity: 434,
+ unauthorizedEntity: 458,
+ },
+ {
+ time: "05:00",
+ authorizedEntity: 618,
+ unauthorizedEntity: 474,
+ },
+ {
+ time: "05:30",
+ authorizedEntity: 654,
+ unauthorizedEntity: 56,
+ },
+ {
+ time: "06:00",
+ authorizedEntity: 114,
+ unauthorizedEntity: 143,
+ },
+ {
+ time: "06:30",
+ authorizedEntity: 384,
+ unauthorizedEntity: 713,
+ },
+ {
+ time: "07:00",
+ authorizedEntity: 383,
+ unauthorizedEntity: 473,
+ },
+ {
+ time: "07:30",
+ authorizedEntity: 313,
+ unauthorizedEntity: 866,
+ },
+ {
+ time: "08:00",
+ authorizedEntity: 648,
+ unauthorizedEntity: 518,
+ },
+ {
+ time: "08:30",
+ authorizedEntity: 268,
+ unauthorizedEntity: 847,
+ },
+ {
+ time: "09:00",
+ authorizedEntity: 347,
+ unauthorizedEntity: 888,
+ },
+ {
+ time: "09:30",
+ authorizedEntity: 981,
+ unauthorizedEntity: 106,
+ },
+ {
+ time: "10:00",
+ authorizedEntity: 913,
+ unauthorizedEntity: 490,
+ },
+ {
+ time: "10:30",
+ authorizedEntity: 701,
+ unauthorizedEntity: 730,
+ },
+ {
+ time: "11:00",
+ authorizedEntity: 834,
+ unauthorizedEntity: 896,
+ },
+ {
+ time: "11:30",
+ authorizedEntity: 954,
+ unauthorizedEntity: 681,
+ },
+ {
+ time: "12:00",
+ authorizedEntity: 342,
+ unauthorizedEntity: 371,
+ },
+ {
+ time: "12:30",
+ authorizedEntity: 518,
+ unauthorizedEntity: 144,
+ },
+ {
+ time: "13:00",
+ authorizedEntity: 71,
+ unauthorizedEntity: 890,
+ },
+ {
+ time: "13:30",
+ authorizedEntity: 484,
+ unauthorizedEntity: 26,
+ },
+ {
+ time: "14:00",
+ authorizedEntity: 705,
+ unauthorizedEntity: 302,
+ },
+ {
+ time: "14:30",
+ authorizedEntity: 128,
+ unauthorizedEntity: 286,
+ },
+ {
+ time: "15:00",
+ authorizedEntity: 292,
+ unauthorizedEntity: 171,
+ },
+ {
+ time: "15:30",
+ authorizedEntity: 418,
+ unauthorizedEntity: 930,
+ },
+ {
+ time: "16:00",
+ authorizedEntity: 903,
+ unauthorizedEntity: 214,
+ },
+ {
+ time: "16:30",
+ authorizedEntity: 195,
+ unauthorizedEntity: 185,
+ },
+ {
+ time: "17:00",
+ authorizedEntity: 151,
+ unauthorizedEntity: 676,
+ },
+ {
+ time: "17:30",
+ authorizedEntity: 347,
+ unauthorizedEntity: 292,
+ },
+ {
+ time: "18:00",
+ authorizedEntity: 404,
+ unauthorizedEntity: 357,
+ },
+ {
+ time: "18:30",
+ authorizedEntity: 465,
+ unauthorizedEntity: 899,
+ },
+ {
+ time: "19:00",
+ authorizedEntity: 950,
+ unauthorizedEntity: 47,
+ },
+ {
+ time: "19:30",
+ authorizedEntity: 962,
+ unauthorizedEntity: 881,
+ },
+ {
+ time: "20:00",
+ authorizedEntity: 41,
+ unauthorizedEntity: 458,
+ },
+ {
+ time: "20:30",
+ authorizedEntity: 357,
+ unauthorizedEntity: 830,
+ },
+ {
+ time: "21:00",
+ authorizedEntity: 145,
+ unauthorizedEntity: 110,
+ },
+ { time: "21:30", authorizedEntity: 521, unauthorizedEntity: 6 },
+ {
+ time: "22:00",
+ authorizedEntity: 548,
+ unauthorizedEntity: 167,
+ },
+ {
+ time: "22:30",
+ authorizedEntity: 786,
+ unauthorizedEntity: 0,
+ },
+ {
+ time: "23:00",
+ authorizedEntity: 470,
+ unauthorizedEntity: 668,
+ },
+ {
+ time: "23:30",
+ authorizedEntity: 840,
+ unauthorizedEntity: 579,
+ },
+ {
+ time: "24:00",
+ authorizedEntity: 840,
+ unauthorizedEntity: 579,
+ },
+ ],
+ };
+
+ const CardHeader: FC = () => {
+ return (
+
+ Detection Summary
+
+
+ );
+ };
+
+ return (
+ <>
+ }>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/authorized-unauthorized-pie/authorized-unauthorized-pie.tsx b/Frontend/src/containers/analytics-container/authorized-unauthorized-pie/authorized-unauthorized-pie.tsx
new file mode 100644
index 0000000..e6e0019
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/authorized-unauthorized-pie/authorized-unauthorized-pie.tsx
@@ -0,0 +1,73 @@
+import React, { useState } from "react";
+import type { FC } from "react";
+import { Select, DatePicker } from "antd";
+import { Card } from "@/components";
+import dayjs from "dayjs";
+import type { Dayjs } from "dayjs";
+import { theme } from "../../../../theme";
+import { PieChart, Pie, Tooltip, ResponsiveContainer } from "recharts";
+
+export const AuthorizedUnauthorizedPieContainer: FC = () => {
+ const [timeOption, setTimeOption] = useState<"day" | "month">("day");
+ const [date, setDate] = useState(dayjs());
+ const data01 = [
+ { name: "Authorized Entity", value: 458, fill: theme.colors.successColor },
+ {
+ name: "Unauthorized Entity",
+ value: 180,
+ fill: theme.colors.dangerColor,
+ },
+ ];
+
+ const CardHeader: FC = () => {
+ return (
+
+ Access proportion
+
+
+ );
+ };
+
+ return (
+ <>
+ }>
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/recent-authorized/recent-authorized.tsx b/Frontend/src/containers/analytics-container/recent-authorized/recent-authorized.tsx
new file mode 100644
index 0000000..f66c579
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/recent-authorized/recent-authorized.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import type { FC } from "react";
+import { Card, Table } from "@/components";
+import { recentActivitiesData, recentActivitiesColumns } from "@/data";
+
+export const RecentAuthorizedContainer: FC = () => {
+ const authorizedEntities = recentActivitiesData
+ .filter((item) => item.entity !== undefined)
+ .slice(0, 5);
+ return (
+ <>
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/recent-unauthorized/recent-unauthorized.tsx b/Frontend/src/containers/analytics-container/recent-unauthorized/recent-unauthorized.tsx
new file mode 100644
index 0000000..00e4592
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/recent-unauthorized/recent-unauthorized.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import type { FC } from "react";
+import { Card, Table } from "@/components";
+import { recentActivitiesData, recentActivitiesColumns } from "@/data";
+
+export const RecentUnauthorizedContainer: FC = () => {
+ const authorizedEntities = recentActivitiesData
+ .filter((item) => item.entity === undefined)
+ .slice(0, 5);
+ return (
+ <>
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/unauthorized-counter/unauthorized-counter.tsx b/Frontend/src/containers/analytics-container/unauthorized-counter/unauthorized-counter.tsx
new file mode 100644
index 0000000..aa0fee1
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/unauthorized-counter/unauthorized-counter.tsx
@@ -0,0 +1,60 @@
+import React, { useState } from "react";
+import type { FC } from "react";
+import { FireOutlined } from "@ant-design/icons";
+import { Statistic, Select, DatePicker } from "antd";
+import { Card } from "@/components";
+import dayjs from "dayjs";
+import type { Dayjs } from "dayjs";
+import { theme } from "../../../../theme";
+
+export const UnauthorizedCounterContainer: FC = () => {
+ const [timeOption, setTimeOption] = useState<"day" | "month">("day");
+ const [date, setDate] = useState(dayjs());
+
+ const CardHeader: FC = () => {
+ return (
+
+ Unauthorized access
+
+
+ );
+ };
+
+ return (
+ <>
+ }>
+ }
+ />
+
+
No of attempts on:
+
+
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/analytics-container/user-area-bar/user-area-bar.tsx b/Frontend/src/containers/analytics-container/user-area-bar/user-area-bar.tsx
new file mode 100644
index 0000000..4d0e545
--- /dev/null
+++ b/Frontend/src/containers/analytics-container/user-area-bar/user-area-bar.tsx
@@ -0,0 +1,171 @@
+import React, { useState, useEffect } from "react";
+import type { FC } from "react";
+import { Select, DatePicker } from "antd";
+import type { SelectProps } from "antd";
+import { Card } from "@/components";
+import dayjs from "dayjs";
+import type { Dayjs } from "dayjs";
+import { theme } from "../../../../theme";
+import {
+ BarChart,
+ Bar,
+ LabelList,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+ ResponsiveContainer,
+} from "recharts";
+import { cameras, authorizedEntitiesData } from "@/data";
+import { getObjectArray } from "@/utils";
+import type { AnyObject, AuthorizedEntity, Camera } from "@/types";
+
+export const UserAreaBarContainer: FC = () => {
+ const cameraOptions = cameras.map((item) => ({
+ label: item.name,
+ value: item.key,
+ }));
+ const entityOptions = authorizedEntitiesData.map((item) => ({
+ label: item.name,
+ value: item.id,
+ }));
+ const [timeOption, setTimeOption] = useState<"day" | "month">("day");
+ const [date, setDate] = useState(dayjs());
+ const [selectedEntities, setSelectedEntities] = useState(
+ []
+ );
+ const [selectedCameras, setSelectedCameras] = useState([]);
+ const [data, setData] = useState([]);
+
+ useEffect(() => {
+ if (selectedEntities.length === 0) {
+ setSelectedEntities(authorizedEntitiesData);
+ }
+ if (selectedCameras.length === 0) {
+ setSelectedCameras(cameras);
+ }
+ /* First construct cameras */
+ let formulatedData = selectedCameras.map((item) => ({ camera: item.name }));
+ /* constuct the count of selected users */
+ for (let i = 0; i < formulatedData.length; i++) {
+ for (let j = 0; j < selectedEntities.length; j++) {
+ formulatedData[i] = {
+ ...formulatedData[i],
+ [selectedEntities[j].id]: Math.floor(Math.random() * 1000),
+ };
+ }
+ }
+ /* set Data */
+ setData(formulatedData);
+ }, [selectedEntities, selectedCameras]);
+
+ const handleEntitySelectChange = (value: string[]) => {
+ const selectedEntitiesObject = getObjectArray(
+ value,
+ "id",
+ authorizedEntitiesData
+ );
+ setSelectedEntities(selectedEntitiesObject);
+ };
+
+ const handleCameraSelectChange = (value: string[]) => {
+ const selectedCamerasObject = getObjectArray(value, "key", cameras);
+ setSelectedCameras(selectedCamerasObject);
+ };
+
+ const CardHeader: FC = () => {
+ return (
+
+ Detection of Authorized Entity per Camera Summary
+
+
+ );
+ };
+
+ return (
+ <>
+ }>
+
+
+
+
+
+
+
+ {selectedEntities.map((item) => (
+
+ ))}
+
+
+
+
+ Date:
+
+
+
+
+ Entities:
+
+
+
+
+ Cameras :
+
+
+
+
+ >
+ );
+};
diff --git a/Frontend/src/containers/index.ts b/Frontend/src/containers/index.ts
index e59e97e..f790699 100644
--- a/Frontend/src/containers/index.ts
+++ b/Frontend/src/containers/index.ts
@@ -1,7 +1,8 @@
export { LayoutContainer } from "./layout-container";
export { VideoStreamContainer } from "./video-stream-container";
export { ContactUsContainer } from "./contact-us-container";
-export { AboutUsOverviewContainer } from "./about-us-overview-container";
-export { AboutUsSolutionContainer } from "./about-us-solution-container";
-export { AboutUsTeamContainer } from "./about-us-team-container";
-export { AboutUsMissionContainer } from "./about-us-mission-container";
+export { AboutUsOverviewContainer } from "./about-us-container/about-us-overview-container";
+export { AboutUsSolutionContainer } from "./about-us-container/about-us-solution-container";
+export { AboutUsTeamContainer } from "./about-us-container/about-us-team-container";
+export { AboutUsMissionContainer } from "./about-us-container/about-us-mission-container";
+export { AnalyticsContainer } from "./analytics-container/analytics-container";
diff --git a/Frontend/src/utils/get-item-object.ts b/Frontend/src/utils/get-item-object.ts
new file mode 100644
index 0000000..da965d2
--- /dev/null
+++ b/Frontend/src/utils/get-item-object.ts
@@ -0,0 +1,13 @@
+import { AnyObject } from "@/types";
+
+/** This is a utility function that returns an object
+ * from array of objects "data" that contain "value" on "key" property if found
+ * otherwise it returns undefined.
+ * */
+export const getItemObject = (
+ value: string | number,
+ key: keyof T,
+ data: T[]
+) => {
+ return data.filter((item) => item[key] === value);
+};
diff --git a/Frontend/src/utils/get-object-array.ts b/Frontend/src/utils/get-object-array.ts
new file mode 100644
index 0000000..a8f4a1c
--- /dev/null
+++ b/Frontend/src/utils/get-object-array.ts
@@ -0,0 +1,16 @@
+import { AnyObject } from "@/types";
+
+/** This is a utility function that returns an array of objects by filtering
+ * array of objects "data" that contain any value in "values" on "key" property.
+ * */
+export const getObjectArray = (
+ values: string[] | number[],
+ key: keyof T,
+ data: T[]
+) => {
+ let items: T[] = [];
+ for (let i = 0; i < values.length; i++) {
+ items = [...items, ...data.filter((item) => item[key] === values[i])];
+ }
+ return items;
+};
diff --git a/Frontend/src/utils/index.ts b/Frontend/src/utils/index.ts
index eeef8c6..44510c8 100644
--- a/Frontend/src/utils/index.ts
+++ b/Frontend/src/utils/index.ts
@@ -1 +1,3 @@
export { getCurrentNav } from "./get-current-nav";
+export { getItemObject } from "./get-item-object";
+export { getObjectArray } from "./get-object-array";