diff --git a/package-lock.json b/package-lock.json
index 73c75b5..47d6f99 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,11 +8,19 @@
"name": "react-chart-js",
"version": "0.1.0",
"dependencies": {
+ "@emotion/react": "^11.11.0",
+ "@emotion/styled": "^11.11.0",
+ "@mui/icons-material": "^5.11.16",
+ "@mui/material": "^5.13.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "chart.js": "^4.3.0",
+ "chartjs-plugin-datalabels": "^2.2.0",
"react": "^18.2.0",
+ "react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
@@ -2137,6 +2145,158 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
+ "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/serialize": "^1.1.2",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
+ "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/sheet": "^1.2.2",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
+ "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.0.tgz",
+ "integrity": "sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/cache": "^11.11.0",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
+ "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/unitless": "^0.8.1",
+ "@emotion/utils": "^1.2.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
+ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
+ },
+ "node_modules/@emotion/styled": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
+ "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.0.0-rc.0",
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
+ "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
+ "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
+ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -2999,11 +3159,272 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
},
+ "node_modules/@kurkle/color": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
+ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
+ },
"node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
+ "node_modules/@mui/base": {
+ "version": "5.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.1.tgz",
+ "integrity": "sha512-xrkDCeu3JQE+JjJUnJnOrdQJMXwKhbV4AW+FRjMIj5i9cHK3BAuatG/iqbf1M+jklVWLk0KdbgioKwK+03aYbA==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/is-prop-valid": "^1.2.0",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@popperjs/core": "^2.11.7",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/base/node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "node_modules/@mui/core-downloads-tracker": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.1.tgz",
+ "integrity": "sha512-qDHtNDO72NcBQMhaWBt9EZMvNiO+OXjPg5Sdk/6LgRDw6Zr3HdEZ5n2FJ/qtYsaT/okGyCuQavQkcZCOCEVf/g==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ }
+ },
+ "node_modules/@mui/icons-material": {
+ "version": "5.11.16",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz",
+ "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.0.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/material": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.1.tgz",
+ "integrity": "sha512-qSnbJZer8lIuDYFDv19/t3s0AXYY9SxcOdhCnGvetRSfOG4gy3TkiFXNCdW5OLNveTieiMpOuv46eXUmE3ZA6A==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/base": "5.0.0-beta.1",
+ "@mui/core-downloads-tracker": "^5.13.1",
+ "@mui/system": "^5.13.1",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@types/react-transition-group": "^4.4.6",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "react-transition-group": "^4.4.5"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/material/node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "node_modules/@mui/private-theming": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.1.tgz",
+ "integrity": "sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/utils": "^5.13.1",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/styled-engine": {
+ "version": "5.12.3",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.12.3.tgz",
+ "integrity": "sha512-AhZtiRyT8Bjr7fufxE/mLS+QJ3LxwX1kghIcM2B2dvJzSSg9rnIuXDXM959QfUVIM3C8U4x3mgVoPFMQJvc4/g==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/cache": "^11.10.8",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.4.1",
+ "@emotion/styled": "^11.3.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/system": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.1.tgz",
+ "integrity": "sha512-BsDUjhiO6ZVAvzKhnWBHLZ5AtPJcdT+62VjnRLyA4isboqDKLg4fmYIZXq51yndg/soDK9RkY5lYZwEDku13Ow==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/private-theming": "^5.13.1",
+ "@mui/styled-engine": "^5.12.3",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/types": {
+ "version": "7.2.4",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
+ "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==",
+ "peerDependencies": {
+ "@types/react": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/utils": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.1.tgz",
+ "integrity": "sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@types/prop-types": "^15.7.5",
+ "@types/react-is": "^18.2.0",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "react": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@mui/utils/node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -3113,6 +3534,23 @@
}
}
},
+ "node_modules/@popperjs/core": {
+ "version": "2.11.7",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
+ "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.2.tgz",
+ "integrity": "sha512-LzqpSrMK/3JBAVBI9u3NWtOhWNw5AMQfrUFYB0+bDHTSw17z++WJLsPsxAuK+oSddsxk4d7F/JcdDPM1M5YAhA==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -4199,6 +4637,22 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-1vz2yObaQkLL7YFe/pme2cpvDsCwI1WXIfL+5eLz0MI9gFG24Re16RzUsI8t9XZn9ZWvgLNDrJBmrqXJO7GNQQ==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
+ "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@@ -5679,6 +6133,25 @@
"node": ">=10"
}
},
+ "node_modules/chart.js": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz",
+ "integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==",
+ "dependencies": {
+ "@kurkle/color": "^0.3.0"
+ },
+ "engines": {
+ "pnpm": ">=7"
+ }
+ },
+ "node_modules/chartjs-plugin-datalabels": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
+ "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
+ "peerDependencies": {
+ "chart.js": ">=3.0.0"
+ }
+ },
"node_modules/check-types": {
"version": "11.2.2",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz",
@@ -5777,6 +6250,14 @@
"wrap-ansi": "^7.0.0"
}
},
+ "node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -6688,6 +7169,15 @@
"utila": "~0.4"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@@ -8068,6 +8558,11 @@
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -8697,6 +9192,19 @@
"he": "bin/he"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -14217,6 +14725,15 @@
"node": ">=14"
}
},
+ "node_modules/react-chartjs-2": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
+ "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
+ "peerDependencies": {
+ "chart.js": "^4.1.1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -14364,6 +14881,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.11.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.2.tgz",
+ "integrity": "sha512-74z9xUSaSX07t3LM+pS6Un0T55ibUE/79CzfZpy5wsPDZaea1F8QkrsiyRnA2YQ7LwE/umaydzXZV80iDCPkMg==",
+ "dependencies": {
+ "@remix-run/router": "1.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.11.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.11.2.tgz",
+ "integrity": "sha512-JNbKtAeh1VSJQnH6RvBDNhxNwemRj7KxCzc5jb7zvDSKRnPWIFj9pO+eXqjM69gQJ0r46hSz1x4l9y0651DKWw==",
+ "dependencies": {
+ "@remix-run/router": "1.6.2",
+ "react-router": "6.11.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -14436,6 +14983,21 @@
}
}
},
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -15576,6 +16138,11 @@
"postcss": "^8.2.15"
}
},
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
"node_modules/sucrase": {
"version": "3.32.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
diff --git a/package.json b/package.json
index 9732411..607cd03 100644
--- a/package.json
+++ b/package.json
@@ -3,11 +3,19 @@
"version": "0.1.0",
"private": true,
"dependencies": {
+ "@emotion/react": "^11.11.0",
+ "@emotion/styled": "^11.11.0",
+ "@mui/icons-material": "^5.11.16",
+ "@mui/material": "^5.13.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "chart.js": "^4.3.0",
+ "chartjs-plugin-datalabels": "^2.2.0",
"react": "^18.2.0",
+ "react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index a11777c..0000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/index.html b/public/index.html
index aa069f2..af76a7f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -2,42 +2,16 @@
-
+
-
-
-
-
- React App
+ content="Web site created using create-react-app" />
+ React | Chart
-
diff --git a/public/logo192.png b/public/logo192.png
deleted file mode 100644
index fc44b0a..0000000
Binary files a/public/logo192.png and /dev/null differ
diff --git a/public/logo512.png b/public/logo512.png
deleted file mode 100644
index a4e47a6..0000000
Binary files a/public/logo512.png and /dev/null differ
diff --git a/public/manifest.json b/public/manifest.json
deleted file mode 100644
index 080d6c7..0000000
--- a/public/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "short_name": "React App",
- "name": "Create React App Sample",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff"
-}
diff --git a/public/pie_statistics_icon.png b/public/pie_statistics_icon.png
new file mode 100644
index 0000000..23da662
Binary files /dev/null and b/public/pie_statistics_icon.png differ
diff --git a/src/App.css b/src/App.css
index 74b5e05..e69de29 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/App.js b/src/App.js
index 3784575..ea2a049 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,25 +1,30 @@
-import logo from './logo.svg';
-import './App.css';
+import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
+import { Container } from '@mui/material';
+
+import MiniDrawer from './components/SideBar';
+import Dashboard from './Pages/Dashboard/index';
+import Inventory from './Pages/Inventory/index';
+import Orders from './Pages/Orders/index';
+import Customers from './Pages/Customers';
+import DataContext from "./Dynamic Data/dataContext";
function App() {
return (
-
+
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
);
}
-export default App;
+export default App;
\ No newline at end of file
diff --git a/src/App.test.js b/src/App.test.js
deleted file mode 100644
index 1f03afe..0000000
--- a/src/App.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import App from './App';
-
-test('renders learn react link', () => {
- render();
- const linkElement = screen.getByText(/learn react/i);
- expect(linkElement).toBeInTheDocument();
-});
diff --git a/src/Dynamic Data/DynamicData.js b/src/Dynamic Data/DynamicData.js
new file mode 100644
index 0000000..c39a4d4
--- /dev/null
+++ b/src/Dynamic Data/DynamicData.js
@@ -0,0 +1,17 @@
+export const fetchCart = async () => {
+ const response = await fetch('https://dummyjson.com/carts')
+ if (!response.ok) {
+ throw new Error('Carts could not be fetched!')
+ } else {
+ return response.json()
+ }
+}
+
+export const fetchProducts = async () => {
+ const response = await fetch('https://dummyjson.com/products?limit=30')
+ if (!response.ok) {
+ throw new Error('Products could not be fetched!')
+ } else {
+ return response.json()
+ }
+}
\ No newline at end of file
diff --git a/src/Dynamic Data/dataContext.js b/src/Dynamic Data/dataContext.js
new file mode 100644
index 0000000..ef24d01
--- /dev/null
+++ b/src/Dynamic Data/dataContext.js
@@ -0,0 +1,28 @@
+import React, { createContext, useEffect, useState } from 'react'
+import { fetchCart, fetchProducts } from './DynamicData';
+export const productContext = createContext();
+
+const DataContext = ({ children }) => {
+ const [products, setProducts] = useState();
+ const [carts, setCarts] = useState();
+ const [filteredProducts, setFilteredProducts] = useState();
+
+ useEffect(() => {
+ fetchProducts()
+ .then(res => {
+ setProducts(res.products);
+ setFilteredProducts(res.products)
+ });
+ fetchCart()
+ .then(res => setCarts(res))
+ }, [])
+
+ return (<>
+
+ {children}
+
+ >)
+}
+
+
+export default DataContext;
\ No newline at end of file
diff --git a/src/Pages/Customers.js b/src/Pages/Customers.js
new file mode 100644
index 0000000..cc0722e
--- /dev/null
+++ b/src/Pages/Customers.js
@@ -0,0 +1,13 @@
+import { Container } from '@mui/material';
+import React, { useEffect } from 'react';
+
+
+const Customers = () => {
+ useEffect(() => { document.title = "Admin | Customers" }, []);
+
+ return (
+ Customers
+ )
+}
+
+export default Customers;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/Cards.js b/src/Pages/Dashboard/Cards.js
new file mode 100644
index 0000000..b6b1074
--- /dev/null
+++ b/src/Pages/Dashboard/Cards.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import DashboardCard from './DashboardCard';
+
+import { Stack } from '@mui/material';
+const Cards = ({ orders = 0, inventory = 0, customers = 0, revenue = 0 }) => {
+
+ const cardsLog = [{ title: "Orders", value: orders }, { title: "Inventory", value: inventory.length }, { title: "Customers", value: customers }, { title: "Revenue", value: revenue.toLocaleString() }]
+ //const formattedNumber = number.toLocaleString("en-US");
+ return (
+
+ {/* useFlexGap helps in wrap */}
+ {cardsLog.map((ele, index) => ())}
+
+ )
+}
+
+export default Cards;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/DashboardCard.js b/src/Pages/Dashboard/DashboardCard.js
new file mode 100644
index 0000000..0c8f2e1
--- /dev/null
+++ b/src/Pages/Dashboard/DashboardCard.js
@@ -0,0 +1,30 @@
+import { Card, Typography, Stack, CardContent, Skeleton } from '@mui/material';
+
+import CurrencyRupeeIcon from '@mui/icons-material/CurrencyRupee';
+import InventoryIcon from '@mui/icons-material/Inventory';
+import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
+import AccountCircleIcon from '@mui/icons-material/AccountCircle';
+const DashboardCard = ({ ele, index }) => {
+ return (
+
+
+
+ {index % 2 === 0 ? index === 0 ? : : index === 1 ? : }
+
+
+ {ele.title}
+
+ {!ele.value || ele.value === "0" ? :
+ {ele.value}
+
+ }
+
+
+
+
+ )
+}
+export default DashboardCard;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/DashboardTable.js b/src/Pages/Dashboard/DashboardTable.js
new file mode 100644
index 0000000..3edca19
--- /dev/null
+++ b/src/Pages/Dashboard/DashboardTable.js
@@ -0,0 +1,59 @@
+import React, { useEffect, useState } from 'react'
+import Table from '@mui/material/Table';
+import TableBody from '@mui/material/TableBody';
+import TableCell from '@mui/material/TableCell';
+import TableContainer from '@mui/material/TableContainer';
+import TableHead from '@mui/material/TableHead';
+import TableRow from '@mui/material/TableRow';
+import Paper from '@mui/material/Paper';
+
+const DashboardTable = ({ orders }) => {
+ const [row, setRow] = useState(null);
+ const [randomIndex, setRandomIndex] = useState(0);
+
+ //Math.floor(Math.random() * arr.length)
+ useEffect(() => {
+ if (orders) {
+ // setRandomIndex(Math.floor(Math.random() * orders.carts.length));
+ // setRow(orders.carts[randomIndex].products)
+ setRow(orders.slice(0, 5));
+ }
+ }, [orders])
+
+
+
+ function BasicTable() {
+ return (<>
+
+
+
+
+ Title
+ Quantity
+ Price
+
+
+
+ {row &&
+ row.map((item) => (
+
+ {item.title}
+ {item.quantity}
+ {item.price}
+
+ ))}
+
+
+
+ >
+ );
+ }
+ return (
+
+ )
+}
+
+export default DashboardTable;
diff --git a/src/Pages/Dashboard/DiscountChart.js b/src/Pages/Dashboard/DiscountChart.js
new file mode 100644
index 0000000..9a184ca
--- /dev/null
+++ b/src/Pages/Dashboard/DiscountChart.js
@@ -0,0 +1,110 @@
+import React, { useState, useEffect } from 'react';
+import { Bar } from "react-chartjs-2";
+import { Box, Skeleton } from '@mui/material';
+
+const PriceVsDiscount = ({ chartsData }) => {
+ const [revenueData, setRevenueData] = useState({
+ labels: [],
+ datasets: [],
+ });
+ const [loader, setLoader] = useState(true);
+ useEffect(() => {
+ if (chartsData) {
+
+ // console.log("chartsData", chartsData)
+ const labels = chartsData.map((product) => {
+ return `User-${product.id}`;
+ });
+ const discountData = chartsData.map((product) => {
+ let discountedValue = product.price * (1 - product.discountPercentage / 100);
+ return discountedValue;
+ });
+ const PriceData = chartsData.map((product) => {
+ return product.price;
+ });
+
+ const dataSource = {
+ labels,
+ datasets: [
+ {
+ label: "DiscountedPrice",
+ data: discountData,
+ backgroundColor: "rgba(255, 0, 0, 0.51)",
+ borderRadius: 10,
+ order: 0,
+ categoryPercentage: 0.75
+ },
+ {
+ label: "Price",
+ data: PriceData,
+ backgroundColor: "rgba(0, 0, 0, 0.41)",
+ borderRadius: 10,
+ order: 1,
+ categoryPercentage: 0.76
+ },
+ ],
+ };
+
+ setRevenueData(dataSource);
+ setLoader(false);
+ }
+
+ }, [chartsData]);
+
+ const options = {
+ responsive: true,
+ scales: {
+ x: {
+ stacked: true,
+ },
+ y: {
+ beginAtZero: true,
+ },
+ },
+ legend: {
+ display: false
+ },
+ }
+
+ // const options = {
+ // responsive: true,
+ // interaction: {
+ // intersect: false,
+ // },
+ // scales: {
+ // x: {
+ // stacked: true,
+ // },
+ // y: {
+ // stacked: true,
+ // beginAtZero: true
+
+ // }
+ // },
+ // plugins: {
+ // legend: {
+ // position: "top",
+ // },
+ // title: {
+ // display: false,
+ // text: "Order Revenue",
+ // },
+ // },
+ // };
+
+ return (<> {loader ?
+ < div style={{ paddingTop: '57%' }
+ } />
+ :
+
+
+
+ }
+ >
+
+ )
+}
+
+export default PriceVsDiscount;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/RatingChart.js b/src/Pages/Dashboard/RatingChart.js
new file mode 100644
index 0000000..2a69999
--- /dev/null
+++ b/src/Pages/Dashboard/RatingChart.js
@@ -0,0 +1,83 @@
+import React, { useState, useEffect } from 'react'
+import { Pie, Scatter } from 'react-chartjs-2';
+import { Skeleton, Box } from '@mui/material';
+
+const RatingChart = ({ chartsData }) => {
+ const [ratingData, setRatingData] = useState({
+ labels: [],
+ datasets: [],
+ });
+ const [loader, setLoader] = useState(true);
+
+ useEffect(() => {
+ if (chartsData) {
+ // console.log("Rating", chartsData.products[0].rating)
+
+ // const counts = {};
+ // for (const num of arr) {
+ // counts[num] = counts[num] ? counts[num] + 1 : 1; //occurrence counter
+ // }
+ const counts = { "4.75 to 5": 0, "4.5 to 4.75": 0, "4.25 to 4.5": 0, "4 to 4.25": 0, "Below 4": 0 };
+ for (const num of chartsData) {
+ if (num.rating <= 5 && num.rating >= 4.75)
+ counts["4.75 to 5"] = counts["4.75 to 5"] + 1;
+ else if (num.rating < 4.75 && num.rating >= 4.5)
+ counts["4.5 to 4.75"] = counts["4.5 to 4.75"] + 1;
+ else if (num.rating < 4.5 && num.rating >= 4.25)
+ counts["4.25 to 4.5"] = counts["4.25 to 4.5"] + 1;
+ else if (num.rating < 4.25 && num.rating >= 4)
+ counts["4 to 4.25"] = counts["4 to 4.25"] + 1;
+ else
+ counts["Below 3"] = counts["Below 3"] + 1;
+
+ // counts[num.rating] = counts[num.rating] ? counts[num.rating] + 1 : 1;
+ }
+
+ // const data = chartsData.products.map((ele) => {
+ // return { x: ele.rating, y: ele.rating }; //Scatter
+ // });
+ const data = Object.values(counts);
+ const ratingLabels = Object.keys(counts);
+ // console.log("Rating", counts)
+
+ const dataSource = {
+ labels: ratingLabels,
+ datasets: [
+ {
+ label: 'Rating',
+ data: data,
+ backgroundColor: [
+ 'rgba(255, 99, 132, 0.5)',
+ 'rgba(54, 162, 235, 0.5)',
+ 'rgba(255, 206, 86, 0.5)',
+ 'rgba(75, 192, 192, 0.5)',
+ 'rgba(153, 102, 255, 0.5)'],
+ },
+ ],
+ };
+ setRatingData(dataSource);
+ setLoader(false);
+ }
+ }, [chartsData]);
+
+ const options = {
+ responsive: true,
+ circumference: 360
+ };
+
+ return (
+ <> {loader ?
+
+
+ :
+
+ {/* */}
+
+ }
+ >
+ )
+}
+
+export default RatingChart;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/RevenueChart.js b/src/Pages/Dashboard/RevenueChart.js
new file mode 100644
index 0000000..0dc0da8
--- /dev/null
+++ b/src/Pages/Dashboard/RevenueChart.js
@@ -0,0 +1,79 @@
+import React, { useState, useEffect } from 'react'
+import { Line } from 'react-chartjs-2';
+import { Skeleton, Box } from '@mui/material';
+
+const RatingChart = ({ chartsData }) => {
+ const [revenueData, setRevenueData] = useState({
+ labels: [],
+ datasets: [],
+ });
+ const [loader, setLoader] = useState(true);
+
+ useEffect(() => {
+ if (chartsData) {
+ // console.log("chartsData", chartsData)
+ const labels = chartsData.map((product) => {
+ return `User-${product.id}`;
+ });
+ const data = chartsData.map((product) => {
+ return product.price;
+ });
+
+ const dataSource = {
+ labels,
+ datasets: [
+ {
+ label: 'Order Revenue',
+ data: data,
+ fill: true,
+ borderColor: "rgb(255, 99, 132)",
+ backgroundColor: "rgba(255, 99, 132, 0.5)",
+ tension: 0.4,
+ pointStyle: "circle"
+ },
+ ],
+ };
+
+ setRevenueData(dataSource);
+ setLoader(false);
+ }
+ }, [chartsData]);
+
+ const options = {
+ type: "line",
+ responsive: true,
+ scales: {
+ y: {
+ beginAtZero: true
+ }
+ },
+ plugins: {
+ legend: {
+ position: "top",
+ },
+ title: {
+ display: false,
+ text: "Order Revenue",
+ },
+ tooltip: {
+ titleColor: "#fff",
+ cornerRadius: 15
+ }
+ },
+ };
+
+ return (
+ <> {loader ?
+
+
+ :
+
+
+ }
+ >
+ )
+}
+
+export default RatingChart;
\ No newline at end of file
diff --git a/src/Pages/Dashboard/index.js b/src/Pages/Dashboard/index.js
new file mode 100644
index 0000000..cb6cbd3
--- /dev/null
+++ b/src/Pages/Dashboard/index.js
@@ -0,0 +1,88 @@
+import React, { useEffect, useState, useContext } from 'react';
+import { Grid, Skeleton, Typography } from '@mui/material';
+
+// import { fetchCart, fetchProducts } from '../../Dynamic Data/DynamicData';
+import { productContext } from '../../Dynamic Data/dataContext';
+import Cards from './Cards';
+import DashboardTable from './DashboardTable';
+import RevenueChart from './RevenueChart';
+import {
+ Chart as ChartJS, Title, Tooltip, Legend, //Common
+
+ CategoryScale, LinearScale, //Line & Bar Chart
+
+ BarElement,//Bar Chart
+
+ PointElement, LineElement, Filler, //Line Chart & Area Chart
+
+ ArcElement, //Pie Chart
+} from "chart.js";
+import RatingChart from './RatingChart';
+import PriceVsDiscount from './DiscountChart';
+
+ChartJS.register(
+ CategoryScale,
+ LinearScale,
+ BarElement,
+ Title,
+ Tooltip,
+ Legend,
+ PointElement, LineElement, Filler,
+ ArcElement,
+);
+
+const Dashboard = () => {
+ useEffect(() => { document.title = "Admin | Dashboard" }, []);
+ //destructure according to index[products, setProducts, carts, setCarts, filteredProducts, setFilteredProducts]
+ const [products, , , , filteredProducts, setFilteredProducts] = useContext(productContext);
+
+ // const [carts, setCarts] = useState();
+ // const [products, setProducts] = useState();
+ const [orders, setOrders] = useState(0);
+ const [revenue, setRevenue] = useState(0);
+ const [loader, setLoader] = useState(true);
+
+ useEffect(() => {
+ setLoader(true);
+ if (products) {
+ let revenue = filteredProducts.reduce((accumulator, object) => {
+ return accumulator + object.price;
+ }, 0);
+ setRevenue(revenue);
+ setOrders(products.length);
+ setLoader(false);
+ }
+ },
+ // eslint-disable-next-line
+ [filteredProducts]);
+ console.log(products);
+
+ return (<>
+
+
+
+
+
+ Revenue
+
+
+
+ Price VS DiscountedPrice
+
+
+
+ <>Recent Orders
+ {loader ?
+
+ :
+
+ }>
+
+
+ Product Rating
+
+
+ >)
+}
+
+export default Dashboard;
\ No newline at end of file
diff --git a/src/Pages/Inventory/InventoryFilter.js b/src/Pages/Inventory/InventoryFilter.js
new file mode 100644
index 0000000..e704b8f
--- /dev/null
+++ b/src/Pages/Inventory/InventoryFilter.js
@@ -0,0 +1,52 @@
+import React, { useState, useContext, useEffect } from 'react'
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+import FormControl from '@mui/material/FormControl';
+import Select from '@mui/material/Select';
+import { productContext } from '../../Dynamic Data/dataContext';
+import { useNavigate } from 'react-router-dom';
+
+const InventoryFilter = () => {
+ const [data, setData] = useState('');
+ //destructure according to index[products, setProducts, carts, setCarts, filteredProducts, setFilteredProducts]
+ const [products, , , , filteredProducts, setFilteredProducts] = useContext(productContext);
+ const [category, setCategory] = useState([]);
+ const navigate = useNavigate();
+ useEffect(() => {
+ //let unique = [...new Set(myArray)]; // unique Elements
+ setCategory([...new Set(products.map((ele) => ele.category))]);
+ }, [])
+
+ useEffect(() => {
+ if (data === "") {
+ setFilteredProducts(products);
+ }
+ else {
+ setFilteredProducts(products.filter((ele) => ele.category === data));
+ }
+ console.log(filteredProducts);
+ }, [data])
+
+ return (
+
+ Filter
+
+
+ );
+}
+
+export default InventoryFilter;
\ No newline at end of file
diff --git a/src/Pages/Inventory/InventoryTable.js b/src/Pages/Inventory/InventoryTable.js
new file mode 100644
index 0000000..a8330a3
--- /dev/null
+++ b/src/Pages/Inventory/InventoryTable.js
@@ -0,0 +1,106 @@
+import React, { useContext, useEffect, useState } from 'react'
+import { Box } from '@mui/material';
+import Table from '@mui/material/Table';
+import TableBody from '@mui/material/TableBody';
+import TableCell from '@mui/material/TableCell';
+import TableContainer from '@mui/material/TableContainer';
+import TableHead from '@mui/material/TableHead';
+import TablePagination from '@mui/material/TablePagination';
+import TableRow from '@mui/material/TableRow';
+import { productContext } from '../../Dynamic Data/dataContext';
+
+const InventoryTable = () => {
+ //destructure according to index [products, setProducts, carts, setCarts, filteredProducts, setFilteredProducts]
+ const [, , , , filteredProducts,] = useContext(productContext)
+ const [rowData, setRowData] = useState();
+ const [page, setPage] = useState(0);
+ const [rowsPerPage, setRowsPerPage] = useState(10);
+
+ useEffect(() => {
+ if (filteredProducts)
+ setRowData(filteredProducts)
+ }, [filteredProducts]);
+
+ const columns = [
+ { id: 'id', label: 'Sr No.', width: 3 + "rem" },
+ { id: 'title', label: 'Title', align: 'left', width: 7 + "rem" },
+ { id: 'stock', label: 'Stock', align: 'center', width: 5 + "rem" },
+ {
+ id: 'price',
+ label: 'Price',
+ width: 5 + "rem",
+ align: 'center',
+ format: (value) => value.toLocaleString(),
+ }
+ ];
+
+ const handleChangePage = (event, newPage) => {
+ if (event.target.getAttribute("data-testid") === "KeyboardArrowRightIcon")
+ setPage(newPage + 1);
+ else if (event.target.getAttribute("data-testid") === "KeyboardArrowLeftIcon")
+ setPage(newPage - 1);
+ else
+ setPage(newPage);
+ // console.log(event.target.getAttribute("data-testid"), newPage)
+ };
+
+ const handleChangeRowsPerPage = (event) => {
+ setRowsPerPage(+event.target.value);
+ setPage(0);
+ };
+
+ return (<>{rowData && <>
+
+
+
+
+ {columns.map((column) => (
+
+ {column.label}
+
+ ))}
+
+
+
+ {rowData
+ .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
+ .map((row) => {
+ return (
+
+ {columns.map((column) => {
+ const value = row[column.id];
+ return (
+
+ {column.format && typeof value === 'number'
+ ? column.format(value)
+ : value}
+
+ );
+ })}
+
+ );
+ })}
+
+
+
+ handleChangePage(e, page)}
+ onRowsPerPageChange={handleChangeRowsPerPage}
+ sx={{
+ padding: 0, bgcolor: "lightcoral", margin: 0
+ }}
+ />
+ >} >
+ );
+}
+
+export default InventoryTable;
\ No newline at end of file
diff --git a/src/Pages/Inventory/index.js b/src/Pages/Inventory/index.js
new file mode 100644
index 0000000..588b96e
--- /dev/null
+++ b/src/Pages/Inventory/index.js
@@ -0,0 +1,35 @@
+import React, { useEffect, useContext } from 'react'
+
+import { Box, Container, Typography, Stack } from '@mui/material';
+import InventoryFilter from './InventoryFilter';
+import InventoryTable from './InventoryTable';
+import { useNavigate } from 'react-router-dom';
+import { productContext } from '../../Dynamic Data/dataContext';
+
+const Inventory = () => {
+ //destructure according to index[products, setProducts, carts, setCarts, filteredProducts, setFilteredProducts]
+ const [products] = useContext(productContext);
+ const navigate = useNavigate();
+
+
+
+ useEffect(() => {
+ document.title = "Admin | Inventory";
+ if (!products) {
+ navigate('/');
+ }
+ }, []);
+
+ return (
+ {products &&
+
+ Inventory
+
+
+
+ }
+
+ );
+}
+
+export default Inventory;
\ No newline at end of file
diff --git a/src/Pages/Orders/index.js b/src/Pages/Orders/index.js
new file mode 100644
index 0000000..7fbec85
--- /dev/null
+++ b/src/Pages/Orders/index.js
@@ -0,0 +1,52 @@
+import { Container } from '@mui/material';
+import React, { useState, useEffect } from 'react'
+import { fetchCart, fetchProducts } from '../../Dynamic Data/DynamicData';
+
+// import { productContext } from '../../Dynamic Data/dataContext';
+
+const Orders = () => {
+ // const [products, setProducts, carts, setCarts] = useContext(productContext)
+ useEffect(() => {
+ document.title = "Admin | Orders";
+ console.log(products, carts);
+
+ }, []);
+ const [carts, setCarts] = useState();
+ const [products, setProducts] = useState();
+ const [orders, setOrders] = useState(0);
+ const [revenue, setRevenue] = useState(0);
+ const [loader, setLoader] = useState(true);
+
+ useEffect(() => {
+ setTimeout(() => {// setTimeout used to test loader
+ fetchCart().then((res) => {
+ setCarts(res);
+ let orders = res.carts.reduce((accumulator, object) => {
+ // console.log(accumulator)
+ return accumulator + object.totalQuantity;
+ }, 0);
+ setOrders(orders);
+
+ let revenue = res.carts.reduce((accumulator, object) => {
+ return accumulator + object.discountedTotal;
+ }, 0);;
+ setRevenue(revenue);
+ });
+ fetchProducts().then((res) => {
+ setProducts(res);
+ // console.log("products", res,products);
+ });
+ setLoader(false);
+ }, 500);
+ },
+ // console.log("cart", carts, "products", products, "orders: ", orders, " inventory: ", products.total, " customers: ", carts.total, " revenue: ", revenue);
+ // eslint-disable-next-line
+ []);
+
+
+ return (
+ Orders
+ )
+}
+
+export default Orders;
\ No newline at end of file
diff --git a/src/components/SideBar.js b/src/components/SideBar.js
new file mode 100644
index 0000000..14ceeab
--- /dev/null
+++ b/src/components/SideBar.js
@@ -0,0 +1,175 @@
+import { useState } from 'react';
+import { styled } from '@mui/material/styles';
+import Box from '@mui/material/Box';
+import MuiDrawer from '@mui/material/Drawer';
+import MuiAppBar from '@mui/material/AppBar';
+import Toolbar from '@mui/material/Toolbar';
+import List from '@mui/material/List';
+import CssBaseline from '@mui/material/CssBaseline';
+import Typography from '@mui/material/Typography';
+import Divider from '@mui/material/Divider';
+import IconButton from '@mui/material/IconButton';
+import MenuIcon from '@mui/icons-material/Menu';
+import ListItem from '@mui/material/ListItem';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import CloseIcon from '@mui/icons-material/Close';
+
+import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';
+import InventoryIcon from '@mui/icons-material/Inventory';
+import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
+import AccountCircleIcon from '@mui/icons-material/AccountCircle';
+
+import { Link, useLocation } from "react-router-dom";
+import { Stack } from '@mui/material';
+import Dashboard from '../Pages/Dashboard';
+
+const drawerWidth = 180;
+
+const openedMixin = (theme) => ({
+ width: drawerWidth,
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ overflowX: 'hidden',
+});
+
+const closedMixin = (theme) => ({
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ overflowX: 'hidden',
+ width: `calc(${theme.spacing(7)} + 1px)`,
+ [theme.breakpoints.up('xs')]: {
+ width: `calc(${theme.spacing(0)} + 1px)`,
+ }, [theme.breakpoints.up('md')]: {
+ width: `calc(${theme.spacing(7)} + 1px)`,
+ },
+});
+
+const DrawerHeader = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'flex-end',
+ padding: theme.spacing(0, 1),
+ // necessary for content to be below app bar
+ ...theme.mixins.toolbar,
+}));
+
+const AppBar = styled(MuiAppBar, {
+ shouldForwardProp: (prop) => prop !== 'open',
+})(({ theme, open }) => ({
+ zIndex: theme.zIndex.drawer + 1,
+ transition: theme.transitions.create(['width', 'margin'], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ ...(open && {
+ marginLeft: drawerWidth,
+ width: `calc(100% - ${drawerWidth}px)`,
+ transition: theme.transitions.create(['width', 'margin'], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ }),
+}));
+
+const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
+ ({ theme, open }) => ({
+ width: drawerWidth,
+ flexShrink: 0,
+ whiteSpace: 'nowrap',
+ boxSizing: 'border-box',
+ ...(open && {
+ ...openedMixin(theme),
+ '& .MuiDrawer-paper': openedMixin(theme),
+ }),
+ ...(!open && {
+ ...closedMixin(theme),
+ '& .MuiDrawer-paper': closedMixin(theme),
+ }),
+ }),
+);
+
+export default function MiniDrawer() {
+ const [open, setOpen] = useState(false);
+ const location = useLocation();
+ let title = location.pathname.slice(1);
+
+ const handleDrawerOpen = () => {
+ setOpen(true);
+ };
+
+ const handleDrawerClose = () => {
+ setOpen(false);
+ };
+
+ return (
+
+
+
+
+
+ {open ? : }
+
+
+ {title ? title : "Dashboard"}
+
+
+
+
+
+
+ Admin
+
+ {open ? : }
+
+
+
+
+
+ {['Dashboard', 'Inventory', 'Orders', 'Customers'].map((text, index) =>
+ (
+
+
+
+
+ {index % 2 === 0 ? index === 0 ? : : index === 1 ? : }
+
+
+
+
+ )
+ )}
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index ec2585e..005eadf 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,13 +1,14 @@
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+ "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
+ background-color: rgb(214, 233, 248);
}
code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
diff --git a/src/index.js b/src/index.js
index d563c0f..2cb1087 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,7 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
-import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
@@ -10,8 +9,3 @@ root.render(
);
-
-// If you want to start measuring performance in your app, pass a function
-// to log results (for example: reportWebVitals(console.log))
-// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 9dfc1c0..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
deleted file mode 100644
index 5253d3a..0000000
--- a/src/reportWebVitals.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const reportWebVitals = onPerfEntry => {
- if (onPerfEntry && onPerfEntry instanceof Function) {
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
- getCLS(onPerfEntry);
- getFID(onPerfEntry);
- getFCP(onPerfEntry);
- getLCP(onPerfEntry);
- getTTFB(onPerfEntry);
- });
- }
-};
-
-export default reportWebVitals;
diff --git a/src/setupTests.js b/src/setupTests.js
deleted file mode 100644
index 8f2609b..0000000
--- a/src/setupTests.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';