diff --git a/package-lock.json b/package-lock.json index 1806669..08ae0d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,27 @@ { - "name": "front-end-my-resturant", + "name": "resturant-dashBord", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "front-end-my-resturant", + "name": "resturant-dashBord", "version": "0.1.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@mui/icons-material": "^7.1.0", + "@mui/material": "^7.1.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^13.5.0", "react": "^19.1.0", + "react-circular-progressbar": "^2.2.0", "react-dom": "^19.1.0", + "react-router-dom": "^7.6.0", "react-scripts": "5.0.1", + "recharts": "^2.15.3", "web-vitals": "^2.1.4" } }, @@ -2350,6 +2357,167 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "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/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", + "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -2962,6 +3130,251 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "license": "MIT" }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz", + "integrity": "sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.0.tgz", + "integrity": "sha512-1mUPMAZ+Qk3jfgL5ftRR06ATH/Esi0izHl1z56H+df6cwIlCWG66RXciUqeJCttbOXOQ5y2DCjLZI/4t3Yg3LA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz", + "integrity": "sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/core-downloads-tracker": "^7.1.0", + "@mui/system": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.1.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz", + "integrity": "sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/utils": "^7.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz", + "integrity": "sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz", + "integrity": "sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/private-theming": "^7.1.0", + "@mui/styled-engine": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.2.tgz", + "integrity": "sha512-edRc5JcLPsrlNFYyTPxds+d5oUovuUxnnDtpJUbP6WMeV4+6eaX/mqai1ZIWT62lCOe0nlrON0s9HDiv5en5bA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.1.0.tgz", + "integrity": "sha512-/OM3S8kSHHmWNOP+NH9xEtpYSG10upXeQ0wLZnfDgmgadTAk5F4MQfFLyZ5FCRJENB3eRzltMmaNl6UtDnPovw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/types": "^7.4.2", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, "node_modules/@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", @@ -3086,6 +3499,16 @@ } } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3647,6 +4070,69 @@ "@types/node": "*" } }, + "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==", + "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.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "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/eslint": { "version": "8.56.12", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", @@ -3811,6 +4297,12 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "license": "MIT" }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, "node_modules/@types/q": { "version": "1.5.8", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", @@ -3829,6 +4321,25 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "license": "MIT" }, + "node_modules/@types/react": { + "version": "19.1.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz", + "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -5631,6 +6142,15 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6361,6 +6881,133 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "license": "MIT" }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "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.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "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/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6455,6 +7102,12 @@ "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", "license": "MIT" }, + "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/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -6687,6 +7340,16 @@ "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==", + "license": "MIT", + "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", @@ -7918,6 +8581,15 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -8155,6 +8827,12 @@ "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==", + "license": "MIT" + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -8840,6 +9518,21 @@ "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==", + "license": "BSD-3-Clause", + "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==", + "license": "MIT" + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -9265,6 +9958,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/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -13778,6 +14480,15 @@ "node": ">=14" } }, + "node_modules/react-circular-progressbar": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-circular-progressbar/-/react-circular-progressbar-2.2.0.tgz", + "integrity": "sha512-cgyqEHOzB0nWMZjKfWN3MfSa1LV3OatcDjPz68lchXQUEiBD5O1WsAtoVK4/DSL0B4USR//cTdok4zCBkq8X5g==", + "license": "MIT", + "peerDependencies": { + "react": ">=0.14.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", @@ -13916,6 +14627,53 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz", + "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.0.tgz", + "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", + "license": "MIT", + "dependencies": { + "react-router": "7.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -13989,6 +14747,37 @@ } } }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "license": "BSD-3-Clause", + "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", @@ -14024,6 +14813,44 @@ "node": ">=8.10.0" } }, + "node_modules/recharts": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz", + "integrity": "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.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==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, "node_modules/recursive-readdir": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", @@ -14822,6 +15649,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -15559,6 +16392,12 @@ "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==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -16065,6 +16904,12 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "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/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -16582,6 +17427,28 @@ "node": ">= 0.8" } }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "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/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 6283ad0..fe33f01 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,22 @@ { - "name": "front-end-my-resturant", + "name": "resturant-dashBord", "version": "0.1.0", "private": true, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@mui/icons-material": "^7.1.0", + "@mui/material": "^7.1.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^13.5.0", "react": "^19.1.0", + "react-circular-progressbar": "^2.2.0", "react-dom": "^19.1.0", + "react-router-dom": "^7.6.0", "react-scripts": "5.0.1", + "recharts": "^2.15.3", "web-vitals": "^2.1.4" }, "scripts": { 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/fonts/PlusJakartaSans/PlusJakartaSans-Medium.ttf b/public/fonts/PlusJakartaSans/PlusJakartaSans-Medium.ttf new file mode 100644 index 0000000..1e58066 Binary files /dev/null and b/public/fonts/PlusJakartaSans/PlusJakartaSans-Medium.ttf differ diff --git a/public/fonts/PlusJakartaSans/PlusJakartaSans-Regular.ttf b/public/fonts/PlusJakartaSans/PlusJakartaSans-Regular.ttf new file mode 100644 index 0000000..1e77059 Binary files /dev/null and b/public/fonts/PlusJakartaSans/PlusJakartaSans-Regular.ttf differ diff --git a/public/fonts/PlusJakartaSans/PlusJakartaSans-SemiBold.ttf b/public/fonts/PlusJakartaSans/PlusJakartaSans-SemiBold.ttf new file mode 100644 index 0000000..49817ef Binary files /dev/null and b/public/fonts/PlusJakartaSans/PlusJakartaSans-SemiBold.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Black.ttf b/public/fonts/inter/Inter_18pt-Black.ttf new file mode 100644 index 0000000..89673de Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Black.ttf differ diff --git a/public/fonts/inter/Inter_18pt-BlackItalic.ttf b/public/fonts/inter/Inter_18pt-BlackItalic.ttf new file mode 100644 index 0000000..b33602f Binary files /dev/null and b/public/fonts/inter/Inter_18pt-BlackItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Bold.ttf b/public/fonts/inter/Inter_18pt-Bold.ttf new file mode 100644 index 0000000..cd13f60 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Bold.ttf differ diff --git a/public/fonts/inter/Inter_18pt-BoldItalic.ttf b/public/fonts/inter/Inter_18pt-BoldItalic.ttf new file mode 100644 index 0000000..0d19c1a Binary files /dev/null and b/public/fonts/inter/Inter_18pt-BoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-ExtraBold.ttf b/public/fonts/inter/Inter_18pt-ExtraBold.ttf new file mode 100644 index 0000000..e71c601 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-ExtraBold.ttf differ diff --git a/public/fonts/inter/Inter_18pt-ExtraBoldItalic.ttf b/public/fonts/inter/Inter_18pt-ExtraBoldItalic.ttf new file mode 100644 index 0000000..df45062 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-ExtraBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-ExtraLight.ttf b/public/fonts/inter/Inter_18pt-ExtraLight.ttf new file mode 100644 index 0000000..f9c6cfc Binary files /dev/null and b/public/fonts/inter/Inter_18pt-ExtraLight.ttf differ diff --git a/public/fonts/inter/Inter_18pt-ExtraLightItalic.ttf b/public/fonts/inter/Inter_18pt-ExtraLightItalic.ttf new file mode 100644 index 0000000..275f305 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-ExtraLightItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Italic.ttf b/public/fonts/inter/Inter_18pt-Italic.ttf new file mode 100644 index 0000000..14d3595 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Italic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Light.ttf b/public/fonts/inter/Inter_18pt-Light.ttf new file mode 100644 index 0000000..acae361 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Light.ttf differ diff --git a/public/fonts/inter/Inter_18pt-LightItalic.ttf b/public/fonts/inter/Inter_18pt-LightItalic.ttf new file mode 100644 index 0000000..f69e18b Binary files /dev/null and b/public/fonts/inter/Inter_18pt-LightItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Medium.ttf b/public/fonts/inter/Inter_18pt-Medium.ttf new file mode 100644 index 0000000..71d9017 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Medium.ttf differ diff --git a/public/fonts/inter/Inter_18pt-MediumItalic.ttf b/public/fonts/inter/Inter_18pt-MediumItalic.ttf new file mode 100644 index 0000000..5c8c8b1 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-MediumItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Regular.ttf b/public/fonts/inter/Inter_18pt-Regular.ttf new file mode 100644 index 0000000..ce097c8 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Regular.ttf differ diff --git a/public/fonts/inter/Inter_18pt-SemiBold.ttf b/public/fonts/inter/Inter_18pt-SemiBold.ttf new file mode 100644 index 0000000..053185e Binary files /dev/null and b/public/fonts/inter/Inter_18pt-SemiBold.ttf differ diff --git a/public/fonts/inter/Inter_18pt-SemiBoldItalic.ttf b/public/fonts/inter/Inter_18pt-SemiBoldItalic.ttf new file mode 100644 index 0000000..d9c9896 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-SemiBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_18pt-Thin.ttf b/public/fonts/inter/Inter_18pt-Thin.ttf new file mode 100644 index 0000000..e68ec47 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-Thin.ttf differ diff --git a/public/fonts/inter/Inter_18pt-ThinItalic.ttf b/public/fonts/inter/Inter_18pt-ThinItalic.ttf new file mode 100644 index 0000000..134e837 Binary files /dev/null and b/public/fonts/inter/Inter_18pt-ThinItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Black.ttf b/public/fonts/inter/Inter_24pt-Black.ttf new file mode 100644 index 0000000..dbb1b3b Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Black.ttf differ diff --git a/public/fonts/inter/Inter_24pt-BlackItalic.ttf b/public/fonts/inter/Inter_24pt-BlackItalic.ttf new file mode 100644 index 0000000..b89d61c Binary files /dev/null and b/public/fonts/inter/Inter_24pt-BlackItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Bold.ttf b/public/fonts/inter/Inter_24pt-Bold.ttf new file mode 100644 index 0000000..46b3583 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Bold.ttf differ diff --git a/public/fonts/inter/Inter_24pt-BoldItalic.ttf b/public/fonts/inter/Inter_24pt-BoldItalic.ttf new file mode 100644 index 0000000..d1c0f53 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-BoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-ExtraBold.ttf b/public/fonts/inter/Inter_24pt-ExtraBold.ttf new file mode 100644 index 0000000..b775c08 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-ExtraBold.ttf differ diff --git a/public/fonts/inter/Inter_24pt-ExtraBoldItalic.ttf b/public/fonts/inter/Inter_24pt-ExtraBoldItalic.ttf new file mode 100644 index 0000000..3461a92 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-ExtraBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-ExtraLight.ttf b/public/fonts/inter/Inter_24pt-ExtraLight.ttf new file mode 100644 index 0000000..2ec6ca3 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-ExtraLight.ttf differ diff --git a/public/fonts/inter/Inter_24pt-ExtraLightItalic.ttf b/public/fonts/inter/Inter_24pt-ExtraLightItalic.ttf new file mode 100644 index 0000000..c634a5d Binary files /dev/null and b/public/fonts/inter/Inter_24pt-ExtraLightItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Italic.ttf b/public/fonts/inter/Inter_24pt-Italic.ttf new file mode 100644 index 0000000..1048b07 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Italic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Light.ttf b/public/fonts/inter/Inter_24pt-Light.ttf new file mode 100644 index 0000000..1a2a6f2 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Light.ttf differ diff --git a/public/fonts/inter/Inter_24pt-LightItalic.ttf b/public/fonts/inter/Inter_24pt-LightItalic.ttf new file mode 100644 index 0000000..ded5a75 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-LightItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Medium.ttf b/public/fonts/inter/Inter_24pt-Medium.ttf new file mode 100644 index 0000000..5c88739 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Medium.ttf differ diff --git a/public/fonts/inter/Inter_24pt-MediumItalic.ttf b/public/fonts/inter/Inter_24pt-MediumItalic.ttf new file mode 100644 index 0000000..be091b1 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-MediumItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Regular.ttf b/public/fonts/inter/Inter_24pt-Regular.ttf new file mode 100644 index 0000000..6b088a7 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Regular.ttf differ diff --git a/public/fonts/inter/Inter_24pt-SemiBold.ttf b/public/fonts/inter/Inter_24pt-SemiBold.ttf new file mode 100644 index 0000000..ceb8576 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-SemiBold.ttf differ diff --git a/public/fonts/inter/Inter_24pt-SemiBoldItalic.ttf b/public/fonts/inter/Inter_24pt-SemiBoldItalic.ttf new file mode 100644 index 0000000..6921df2 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-SemiBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_24pt-Thin.ttf b/public/fonts/inter/Inter_24pt-Thin.ttf new file mode 100644 index 0000000..3505b35 Binary files /dev/null and b/public/fonts/inter/Inter_24pt-Thin.ttf differ diff --git a/public/fonts/inter/Inter_24pt-ThinItalic.ttf b/public/fonts/inter/Inter_24pt-ThinItalic.ttf new file mode 100644 index 0000000..a3e6feb Binary files /dev/null and b/public/fonts/inter/Inter_24pt-ThinItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Black.ttf b/public/fonts/inter/Inter_28pt-Black.ttf new file mode 100644 index 0000000..66a252f Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Black.ttf differ diff --git a/public/fonts/inter/Inter_28pt-BlackItalic.ttf b/public/fonts/inter/Inter_28pt-BlackItalic.ttf new file mode 100644 index 0000000..3c8fdf9 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-BlackItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Bold.ttf b/public/fonts/inter/Inter_28pt-Bold.ttf new file mode 100644 index 0000000..d17828b Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Bold.ttf differ diff --git a/public/fonts/inter/Inter_28pt-BoldItalic.ttf b/public/fonts/inter/Inter_28pt-BoldItalic.ttf new file mode 100644 index 0000000..6fce50a Binary files /dev/null and b/public/fonts/inter/Inter_28pt-BoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-ExtraBold.ttf b/public/fonts/inter/Inter_28pt-ExtraBold.ttf new file mode 100644 index 0000000..6d87cae Binary files /dev/null and b/public/fonts/inter/Inter_28pt-ExtraBold.ttf differ diff --git a/public/fonts/inter/Inter_28pt-ExtraBoldItalic.ttf b/public/fonts/inter/Inter_28pt-ExtraBoldItalic.ttf new file mode 100644 index 0000000..1a56735 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-ExtraBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-ExtraLight.ttf b/public/fonts/inter/Inter_28pt-ExtraLight.ttf new file mode 100644 index 0000000..d42b3f5 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-ExtraLight.ttf differ diff --git a/public/fonts/inter/Inter_28pt-ExtraLightItalic.ttf b/public/fonts/inter/Inter_28pt-ExtraLightItalic.ttf new file mode 100644 index 0000000..90e2f20 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-ExtraLightItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Italic.ttf b/public/fonts/inter/Inter_28pt-Italic.ttf new file mode 100644 index 0000000..c2a143a Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Italic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Light.ttf b/public/fonts/inter/Inter_28pt-Light.ttf new file mode 100644 index 0000000..5eeff3a Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Light.ttf differ diff --git a/public/fonts/inter/Inter_28pt-LightItalic.ttf b/public/fonts/inter/Inter_28pt-LightItalic.ttf new file mode 100644 index 0000000..6b90b76 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-LightItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Medium.ttf b/public/fonts/inter/Inter_28pt-Medium.ttf new file mode 100644 index 0000000..00120fe Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Medium.ttf differ diff --git a/public/fonts/inter/Inter_28pt-MediumItalic.ttf b/public/fonts/inter/Inter_28pt-MediumItalic.ttf new file mode 100644 index 0000000..7481e7b Binary files /dev/null and b/public/fonts/inter/Inter_28pt-MediumItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Regular.ttf b/public/fonts/inter/Inter_28pt-Regular.ttf new file mode 100644 index 0000000..855b6f4 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Regular.ttf differ diff --git a/public/fonts/inter/Inter_28pt-SemiBold.ttf b/public/fonts/inter/Inter_28pt-SemiBold.ttf new file mode 100644 index 0000000..8b84efc Binary files /dev/null and b/public/fonts/inter/Inter_28pt-SemiBold.ttf differ diff --git a/public/fonts/inter/Inter_28pt-SemiBoldItalic.ttf b/public/fonts/inter/Inter_28pt-SemiBoldItalic.ttf new file mode 100644 index 0000000..2e22c5a Binary files /dev/null and b/public/fonts/inter/Inter_28pt-SemiBoldItalic.ttf differ diff --git a/public/fonts/inter/Inter_28pt-Thin.ttf b/public/fonts/inter/Inter_28pt-Thin.ttf new file mode 100644 index 0000000..94e6108 Binary files /dev/null and b/public/fonts/inter/Inter_28pt-Thin.ttf differ diff --git a/public/fonts/inter/Inter_28pt-ThinItalic.ttf b/public/fonts/inter/Inter_28pt-ThinItalic.ttf new file mode 100644 index 0000000..d3d44cd Binary files /dev/null and b/public/fonts/inter/Inter_28pt-ThinItalic.ttf differ diff --git a/public/icon.ico b/public/icon.ico new file mode 100644 index 0000000..7dcdb85 Binary files /dev/null and b/public/icon.ico differ diff --git a/public/image.png b/public/image.png new file mode 100644 index 0000000..01900c7 Binary files /dev/null and b/public/image.png differ diff --git a/public/images/compeoter.png b/public/images/compeoter.png new file mode 100644 index 0000000..5ea562d Binary files /dev/null and b/public/images/compeoter.png differ diff --git a/public/images/hand.png b/public/images/hand.png new file mode 100644 index 0000000..eb6e5d4 Binary files /dev/null and b/public/images/hand.png differ diff --git a/public/images/icons/email.png b/public/images/icons/email.png new file mode 100644 index 0000000..1ebd9fb Binary files /dev/null and b/public/images/icons/email.png differ diff --git a/public/images/icons/image.png b/public/images/icons/image.png new file mode 100644 index 0000000..2c15c96 Binary files /dev/null and b/public/images/icons/image.png differ diff --git a/public/images/icons/key.png b/public/images/icons/key.png new file mode 100644 index 0000000..cae4f7f Binary files /dev/null and b/public/images/icons/key.png differ diff --git a/public/images/icons/pen.png b/public/images/icons/pen.png new file mode 100644 index 0000000..781073a Binary files /dev/null and b/public/images/icons/pen.png differ diff --git a/public/images/icons/rocket.png b/public/images/icons/rocket.png new file mode 100644 index 0000000..ff31880 Binary files /dev/null and b/public/images/icons/rocket.png differ diff --git a/public/images/waiterss2.png b/public/images/waiterss2.png new file mode 100644 index 0000000..6273f68 Binary files /dev/null and b/public/images/waiterss2.png differ diff --git a/public/images/waiterss4.png b/public/images/waiterss4.png new file mode 100644 index 0000000..50848f0 Binary files /dev/null and b/public/images/waiterss4.png differ diff --git a/public/images/waitress.png b/public/images/waitress.png new file mode 100644 index 0000000..c04a1d5 Binary files /dev/null and b/public/images/waitress.png differ diff --git a/public/images/waitress3.png b/public/images/waitress3.png new file mode 100644 index 0000000..44d630f Binary files /dev/null and b/public/images/waitress3.png differ diff --git a/public/index.html b/public/index.html index aa069f2..73145cb 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - + - - - - React App + + + Restaurant
- + diff --git a/src/App.css b/src/App.css index 74b5e05..47d6bb5 100644 --- a/src/App.css +++ b/src/App.css @@ -22,6 +22,7 @@ justify-content: center; font-size: calc(10px + 2vmin); color: white; + } .App-link { @@ -36,3 +37,88 @@ transform: rotate(360deg); } } + + + + + +/* CUSTOM FONTS */ + + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Thin.ttf'); + font-weight: 100; +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-ExtraLight.ttf'); + font-weight: 200; +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Light.ttf'); + font-weight: 300; + +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Regular.ttf'); + font-weight: 400; + +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Medium.ttf'); + font-weight: 500; + +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-SemiBold.ttf'); + font-weight: 600; +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Bold.ttf'); + font-weight: 700; + +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-ExtraBold.ttf'); + font-weight: 800; +} + +@font-face { + font-family: INTER; + src: url('../public/fonts/inter/Inter_18pt-Black.ttf'); + font-weight: 900; +} + +@font-face { + font-family: PlusJakartaSans ; + src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-Medium.ttf'); + font-weight: 500; +} + +@font-face { + font-family: PlusJakartaSans ; + src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-SemiBold.ttf'); + font-weight: 600; +} + +@font-face { + font-family: PlusJakartaSans ; + src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-Regular.ttf'); + font-weight: 400; +} +/* === CUSTOM FONTS ===*/ + diff --git a/src/App.js b/src/App.js index 3784575..4311be0 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,48 @@ -import logo from './logo.svg'; +import React from 'react'; import './App.css'; +import { ThemeProvider } from '@mui/material/styles'; +import theme from './theme'; +import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import LoginForm from './components/Authentication/SignUp_In/LoginForm'; +import RegisterForm from './components/Authentication/SignUp_In/RegisterForm'; +import ForgetPassword from './components/Authentication/ForgetPassword/ForgetFormMain'; + + +import Dashboard from './components/Home/Dashboard/Dashboard'; +import Inventory from './components/Home/Inventory/Inventory'; +import Analytics from './components/Home/Analytics&Reporting/Analytics'; +import Supplier from './components/Home/Supplier/Supplier'; +import Cashier from './components/Home/Cashier/Cashier'; +import CreateYourRestaurant from './components/Home/CreateYourRestaurant/CreateRestaurant'; + +import Training from './components/Home/Training/Training'; +import RestaurantProfile from './components/Home/RestaurantProfile/RestaurantProfile'; +import HostKitchen from './components/Home/HostKitchen/HostKitchen'; +import Settings from './components/Home/Settings/Setting'; function App() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
+ + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); } diff --git a/src/components/Authentication/ForgetPassword/Congratulations.js b/src/components/Authentication/ForgetPassword/Congratulations.js new file mode 100644 index 0000000..8f6fec2 --- /dev/null +++ b/src/components/Authentication/ForgetPassword/Congratulations.js @@ -0,0 +1,132 @@ +import React from 'react'; +import { Box, TextField, Typography, Button, useTheme } from '@mui/material'; +import { useNavigate } from 'react-router-dom'; + +const Congratulations = ({ emailOrPhone, setEmailOrPhone }) => { + const navigate = useNavigate(); + const theme = useTheme(); + return ( + + + + + + + + + + Congratulations! + + + + Your password has been successfully updated. Thank you for choosing our service + + + + {/* زر التنقل إلى صفحة تسجيل الدخول */} + + + ); +}; + +export default Congratulations; + diff --git a/src/components/Authentication/ForgetPassword/EmailInputSection.js b/src/components/Authentication/ForgetPassword/EmailInputSection.js new file mode 100644 index 0000000..dd801be --- /dev/null +++ b/src/components/Authentication/ForgetPassword/EmailInputSection.js @@ -0,0 +1,147 @@ +// EmailInputSection.js +import React, { useState } from 'react'; +import { Box, Button, TextField, Typography ,useTheme} from '@mui/material'; + +const EmailInputSection = ({ emailOrPhone, setEmailOrPhone }) => { + const theme = useTheme(); + const [currentSlide, setCurrentSlide] = useState(0); + const slides = [0, 1, 2, 3]; + + const handleSend = () => { + // عملية الإرسال + }; + + const handleNext = () => { + if (currentSlide < slides.length - 1) { + setCurrentSlide(prev => prev + 1); + } + }; + + const handleBack = () => { + if (currentSlide > 0) { + setCurrentSlide(prev => prev - 1); + } + }; + return ( + <> + + + + + + Forget Password + + + + Enter your email to reset it and regain access to your account. + + + + + Email/Phone + + setEmailOrPhone(e.target.value)} + sx={{ + '& input': { + fontWeight: 500, + fontSize: '15px' + }, + '& input::placeholder': { + color: '#969BA7' + }, + '& .MuiOutlinedInput-root': { + borderRadius: '10px', + transition: '0.3s', + '&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز + borderColor: '#FF914D', + boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف + } + }, + '& .MuiOutlinedInput-root.Mui-focused': { + borderColor: '#3f51b5', + boxShadow: '0 0 0 2px rgba(63,81,181,0.1)' + } + }} + /> + + + {/* send */} + + + + By log in, I agree to the  + Terms of Service and  + Privacy Policy + + + ); +}; + +export default EmailInputSection; diff --git a/src/components/Authentication/ForgetPassword/ForgetFormMain.js b/src/components/Authentication/ForgetPassword/ForgetFormMain.js new file mode 100644 index 0000000..84cbbae --- /dev/null +++ b/src/components/Authentication/ForgetPassword/ForgetFormMain.js @@ -0,0 +1,125 @@ +import React, { useState } from 'react'; +import { Box, Stack ,useTheme} from '@mui/material'; +import Side from './Side'; +import EmailInputSection from './EmailInputSection'; +import OtpVerification from './OtpVerification'; +import NewPassword from './NewPassword'; +import Congratulations from './Congratulations'; + + + +const ForgetForm = () => { + const [emailOrPhone, setEmailOrPhone] = useState(''); + const [currentSlide, setCurrentSlide] = useState(0); + const theme = useTheme(); + const slides = [ + { component: EmailInputSection, title: "Email Verification" }, + { component: OtpVerification, title: "OTP Verification" }, + { component: NewPassword, title: "New Password" }, + { component: Congratulations, title: "Congratulations" } + ]; + + const handleNext = () => { + if (currentSlide < slides.length - 1) { + setCurrentSlide(prev => prev + 1); + } + }; + + const handleBack = () => { + if (currentSlide > 0) { + setCurrentSlide(prev => prev - 1); + } + }; + + const CurrentComponent = slides[currentSlide].component; + + return ( + + {/* ✅ Sidebar يظهر فقط من sm+ */} + + + + + {/* ✅ Form */} + + + + + + {/* إظهار المكون الحالي فقط */} + + + + + + + {/* ✅ مؤشر الشرائح السفلي */} + + {slides.map((_, index) => ( + setCurrentSlide(index)} // يمكنك تفعيلها لاحقًا + /> + ))} + + + + ); +}; + +export default ForgetForm; diff --git a/src/components/Authentication/ForgetPassword/NewPassword.js b/src/components/Authentication/ForgetPassword/NewPassword.js new file mode 100644 index 0000000..2dcea07 --- /dev/null +++ b/src/components/Authentication/ForgetPassword/NewPassword.js @@ -0,0 +1,217 @@ +// EmailInputSection.js +import React, { useState } from 'react'; +import { Box, Button, TextField, Typography } from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import { IconButton, InputAdornment } from '@mui/material'; +import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; +import { VisibilityOutlined } from '@mui/icons-material'; + +const EmailInputSection = ({ emailOrPhone, setEmailOrPhone }) => { + const theme = useTheme(); + const handleTogglePassword = () => { + setShowPassword((prev) => !prev); + }; + + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [currentSlide, setCurrentSlide] = useState(0); + const slides = [0, 1, 2, 3]; + + const handleSend = () => { + // عملية الإرسال + }; + const handleToggleConfirmPassword = () => { + setShowConfirmPassword((prev) => !prev); + }; + + const handleNext = () => { + if (currentSlide < slides.length - 1) { + setCurrentSlide(prev => prev + 1); + } + }; + + const handleBack = () => { + if (currentSlide > 0) { + setCurrentSlide(prev => prev - 1); + } + }; + return ( + <> + + + + + + Create a New Password + + + + Enter your email to reset it and regai access to your account. + + + {/* Password Input */} + + + Password + + + + {showPassword ? : } + + + ) + }} + /> + + + + {/* Confirm Password Input */} + + + Confirm Password + + + + {showConfirmPassword ? : } + + + ) + }} + /> + + + {/* send */} + + + By log in, I agree to the  + Terms of Service and  + Privacy Policy + + + ); +}; + +export default EmailInputSection; diff --git a/src/components/Authentication/ForgetPassword/OtpVerification.js b/src/components/Authentication/ForgetPassword/OtpVerification.js new file mode 100644 index 0000000..dd36b1c --- /dev/null +++ b/src/components/Authentication/ForgetPassword/OtpVerification.js @@ -0,0 +1,183 @@ +import React, { useState, useRef } from 'react'; +import { Box, TextField, Typography, Button, Stack ,useTheme} from '@mui/material'; + +const OtpVerification = () => { + const [emailOrPhone, setEmailOrPhone] = useState(''); + const [currentSlide, setCurrentSlide] = useState(0); + const slides = [0, 1, 2, 3]; + + const [otp, setOtp] = useState(Array(7).fill('')); + const inputRefs = useRef(Array(7).fill().map(() => React.createRef())); + + const handleSend = () => { + const otpCode = otp.join(''); + console.log('Submitted OTP:', otpCode); + // عملية التحقق من الكود + }; + + const handleOtpChange = (e, index) => { + const value = e.target.value; + if (!/^[0-9]?$/.test(value)) return; + + const newOtp = [...otp]; + newOtp[index] = value; + setOtp(newOtp); + + if (value && index < 6) { + inputRefs.current[index + 1].current.focus(); + } + }; + + const handleKeyDown = (e, index) => { + if (e.key === 'Backspace' && !otp[index] && index > 0) { + inputRefs.current[index - 1].current.focus(); + } + }; + + const handleNext = () => { + if (currentSlide < slides.length - 1) { + setCurrentSlide(prev => prev + 1); + } + }; + + const handleBack = () => { + if (currentSlide > 0) { + setCurrentSlide(prev => prev - 1); + } + }; + const theme = useTheme(); + + return ( + <> + + + + + + Enter OTP Verification + + + + Kindly enter the OTP code sent to your registered email/phone for account verification. + + + + + + {otp.map((digit, index) => ( + handleOtpChange(e, index)} + onKeyDown={(e) => handleKeyDown(e, index)} + inputProps={{ + maxLength: 1, + style: { + textAlign: 'center', + fontSize: '20px', + }, + }} + sx={{ + width: { xs: '3rem', sm: '3.25rem', md: '4rem' }, + height: { xs: '3rem', sm: '3.25rem', md: '4rem' }, + '& .MuiOutlinedInput-root': { + borderRadius: '0.5rem', + height: '100%', // تأكيد تطابق الطول + '& fieldset': { + borderColor: '#ccc', + }, + '&:hover fieldset': { + borderColor: theme.palette.primary.main, + }, + '&.Mui-focused fieldset': { + borderColor: theme.palette.primary.main, + }, + }, + '& .MuiInputBase-input': { + color: theme.palette.primary.main, + textAlign: 'center', + fontSize: '20px', + padding: 0, + height: '100%', + }, + }} + /> + ))} + + + + + + + + + By log in, I agree to the  + Terms of Service and  + Privacy Policy + + + ); +}; + +export default OtpVerification; diff --git a/src/components/Authentication/ForgetPassword/Side.js b/src/components/Authentication/ForgetPassword/Side.js new file mode 100644 index 0000000..e9c8712 --- /dev/null +++ b/src/components/Authentication/ForgetPassword/Side.js @@ -0,0 +1,187 @@ +import React from 'react'; +import { Box, Typography, Stack, Button ,useTheme } from '@mui/material'; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; +import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; + +const steps = [ + { + title: 'Forget Password', + description: 'Provide an email to change your password', + icon: '/images/icons/key.png', + }, + { + title: 'Verify your email', + description: 'Enter your otp verification', + icon: '/images/icons/email.png', + }, + { + title: 'Create a new password', + description: 'Create your a new password', + icon: '/images/icons/pen.png', + }, + { + title: 'Welcome to KitchPlus app', + description: 'Get up and running in 3 minutes', + icon: '/images/icons/rocket.png', + }, +]; + +const Side = ({ currentStepIndex, onNext, onBack }) => { + const theme = useTheme(); + return ( + + + Step for change your password + + + Instructions for secure password modification. Follow simple steps for password change. + + + + {steps.map((step, index) => ( + + {index !== steps.length - 1 && ( + + )} + + + + {step.title} + + + + + + {step.title} + + + {step.description} + + + + ))} + + + {/* ... (بقية محتوى الـ Side كما هو بدون تغيير) ... */} + + {/* أزرار التنقل */} + + + {/* Back */} + + {/* Next */} + + + + ); +}; + +export default Side; \ No newline at end of file diff --git a/src/components/Authentication/SignUp_In/LoginForm.js b/src/components/Authentication/SignUp_In/LoginForm.js new file mode 100644 index 0000000..ee7b8a3 --- /dev/null +++ b/src/components/Authentication/SignUp_In/LoginForm.js @@ -0,0 +1,349 @@ +import React, { useState } from 'react'; +import { TextField, Button, Typography, Stack, Box, IconButton, InputAdornment } from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; +import { VisibilityOutlined } from '@mui/icons-material'; +import SidePanel from './SidePanel'; // استدعاء SidePanel من نفس المجلد أو حسب المسار المناسب +import { useNavigate } from 'react-router-dom'; +import { Link } from 'react-router-dom'; + + +const LoginForm = () => { + + const navigate = useNavigate(); + const theme = useTheme(); + const [showPassword, setShowPassword] = useState(false); + + const handleTogglePassword = () => { + setShowPassword((prev) => !prev); + }; + const handleLogin = () => { + // بعد تنفيذ عملية تسجيل الدخول بنجاح، يتم التوجيه + navigate('/dashboard'); + }; + return ( + + + + {/* SidePanel ثابت */} + + + {/* Login Content */} + + + + + + {/* Logo */} + + logo + + + + Login + + + + Enter your username and password to access your account securely. Welcome back to our service! + + + {/* Email Input */} + + + Email + + + + + {/* Password Input */} + + + Password + + + + {showPassword ? : } + + + ) + }} + /> + + + {/* Login Button */} + + + + + {/* Divider */} + + + + Or + + + + + {/* Google Button */} + + + {/* Facebook Button */} + + + + {/* Register Link */} + + Don’t have an account?{' '} + + Register + + + + {/* ForgetPassword Link */} + + Did you forget the password?{' '} + + Forget Password + + + + {/* Terms */} + + By logging in, I agree to the{' '} + + Terms of Service + {' '} + and{' '} + + Privacy Policy + . + + + + + + + ); +}; + +export default LoginForm; diff --git a/src/components/Authentication/SignUp_In/RegisterForm.js b/src/components/Authentication/SignUp_In/RegisterForm.js new file mode 100644 index 0000000..5b9bade --- /dev/null +++ b/src/components/Authentication/SignUp_In/RegisterForm.js @@ -0,0 +1,409 @@ +import React, { useState } from 'react'; +import { TextField, Button, Typography, Stack, Box, IconButton, InputAdornment } from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; +import { VisibilityOutlined } from '@mui/icons-material'; +import SidePanel from './SidePanel'; +import { Link } from 'react-router-dom'; +const Register = () => { + const theme = useTheme(); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); + + const handleTogglePassword = () => { + setShowPassword((prev) => !prev); + }; + + const handleToggleConfirmPassword = () => { + setShowConfirmPassword((prev) => !prev); + }; + + return ( + + {/* SidePanel ثابت */} + + + + {/* Login Content */} + + + + + + {/* Logo */} + + logo + + + + Register + + + + Please fill out the registration form with accurate information to + create your account successfully. + + + {/* Email Input */} + + + Email + + + + + {/* Password Input */} + + + Password + + + + {showPassword ? : } + + + ) + }} + /> + + + {/* Confirm Password Input */} + + + Confirm Password + + + + {showConfirmPassword ? : } + + + ) + }} + /> + + + {/* Login Button */} + + + + + {/* Divider */} + + + + Or + + + + + {/* Google Button */} + + + {/* Facebook Button */} + + + {/* login Link */} + + + Already have an account?{' '} + + Login + + + + {/* Terms */} + + By log in, I agree to the and {' '} + + Terms of Service + {' '} + and{' '} + + Privacy Policy + . + + + + + + + ); +}; + +export default Register; \ No newline at end of file diff --git a/src/components/Authentication/SignUp_In/SidePanel.js b/src/components/Authentication/SignUp_In/SidePanel.js new file mode 100644 index 0000000..2e78203 --- /dev/null +++ b/src/components/Authentication/SignUp_In/SidePanel.js @@ -0,0 +1,194 @@ +import React, { useState, useEffect } from 'react'; + + +import { + Button, + Typography, + Stack, + Box +} from '@mui/material'; + +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; // استيراد أيقونة السهم + +const SidePanel = ({ setMode, mode }) => { + const [currentSlide, setCurrentSlide] = useState(0); + + const slides = [ + { + image: '/images/waitress3.png', + title: "Welcome to our cutting-edge postal application,", + description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient." + }, + { + image: '/images/waitress3.png', + title: "Second Slide Title", + description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient." + }, + { + image: '/images/waitress3.png', + title: "Third Slide Title", + description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient." + }, + { + image: '/images/waitress3.png', + title: "Fourth Slide Title", + description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient." + } + ]; + + useEffect(() => { + const interval = setInterval(() => { + setCurrentSlide((prev) => (prev + 1) % slides.length); + }, 5000); + return () => clearInterval(interval); + }, [slides.length]); + + return ( + + + + + + {/* الصورة الحالية */} + {`Slide + + {/* مربع النص في الأسفل */} + + + + + {slides[currentSlide].description} + + + + {/* مؤشرات الشرائح */} + + {slides.map((_, index) => ( + setCurrentSlide(index)} + /> + ))} + + + + + + + + + ) +} + +export default SidePanel; \ No newline at end of file diff --git a/src/components/Home/Analytics&Reporting/Analytics.js b/src/components/Home/Analytics&Reporting/Analytics.js new file mode 100644 index 0000000..8b8b5c6 --- /dev/null +++ b/src/components/Home/Analytics&Reporting/Analytics.js @@ -0,0 +1,112 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; +import AnalyticsContect from './AnalyticsContect'; + +const drawerWidth = 230; + +const AnalyticsPage = () => { + const [timeFrame, setTimeFrame] = useState('month'); + + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة التحقق من المنتجات + useEffect(() => { + const checkProducts = async () => { + setIsLoading(true); + const productsExist = await checkIfProductsExist(); // استبدل بمنطقك + setHasProducts(productsExist); + setIsLoading(false); + }; + + checkProducts(); + }, []); + + const checkIfProductsExist = async () => { + return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + return ( + + + + + + + + + + + {isLoading ? ( + <> + + + + + ) : ( + + )} + + + + ); +}; + +export default AnalyticsPage; diff --git a/src/components/Home/Analytics&Reporting/AnalyticsContect.js b/src/components/Home/Analytics&Reporting/AnalyticsContect.js new file mode 100644 index 0000000..8415cee --- /dev/null +++ b/src/components/Home/Analytics&Reporting/AnalyticsContect.js @@ -0,0 +1,227 @@ +import React, { useState, useEffect } from 'react'; +import StatisticsCard from './StatisticsCard'; +import TopSellingProduct from './TopSellingProduct'; +import SalesByLocation from './SalesByLocation'; +import { + Box, + useTheme, + useMediaQuery, + Skeleton, + Button, + Typography, + ButtonGroup +} from '@mui/material'; +import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined'; + +const AnalyticsPage = () => { + const [timeFrame, setTimeFrame] = useState('month'); + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + +const dailyData = [ + { date: '10:00', visitors: 1500, conversions: 300 }, + { date: '11:00', visitors: 1800, conversions: 320 }, +]; + +const weeklyData = [ + { label: 'Week 1', visitors: 1500, conversions: 200 }, + { label: 'Week 2', visitors: 2300, conversions: 400 }, +]; + +const monthlyData = [ + { label: 'Jan', visitors: 15000, conversions: 3000 }, + { label: 'Feb', visitors: 18000, conversions: 4000 }, +]; + +const yearlyData = [ + { label: '2024', visitors: 25000, conversions: 7000 }, + { label: '2025', visitors: 38000, conversions: 12000 }, +]; + + + const getData = () => { + switch (timeFrame) { + case '24h': + return dailyData; + case '7d': + return weeklyData; + case '30d': + return monthlyData; + case '12m': + return yearlyData; + case 'all': + return [...yearlyData, ...monthlyData, ...weeklyData, ...dailyData]; + default: + return dailyData; + } + }; + + const topSellingProducts = [ + { product: 'Apple Watch', sales: 150, amount: 45000, price: 299, status: 'Published' }, + { product: 'Samsung Galaxy', sales: 90, amount: 36000, price: 400, status: 'Low Stock' }, + { product: 'Sony Headphones', sales: 60, amount: 18000, price: 299, status: 'Draft' }, + ]; + + const salesData = [ + { country: 'United Kingdom', amount: 17678, change: 12, sales: 340 }, + { country: 'Spain', amount: 5500, change: -5, sales: 100 }, + { country: 'Germany', amount: 24189, change: -25, sales: 540 }, + ]; + + useEffect(() => { + const checkProducts = async () => { + setIsLoading(true); + const productsExist = await new Promise((resolve) => + setTimeout(() => resolve(true), 1500) + ); + setHasProducts(productsExist); + setIsLoading(false); + }; + checkProducts(); + }, []); + + useEffect(() => { + const handleResize = () => { + setSidebarOpen(window.innerWidth >= theme.breakpoints.values.md); + }; + handleResize(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + return ( + + {/* Header Buttons */} + + + {[ + { label: 'All Time', value: 'all' }, + { label: '12 Months', value: '12m' }, + { label: '30 Days', value: '30d' }, + { label: '7 Days', value: '7d' }, + { label: '24 Hour', value: '24h' }, + ].map(({ label, value }) => ( + + ))} + + + + + + + + + + {/* Data Sections */} + + + + + + + + + + {/* Chart Section */} + + {isLoading ? ( + <> + + + + + ) : ( + + )} + + + ); +}; + +export default AnalyticsPage; diff --git a/src/components/Home/Analytics&Reporting/SalesByLocation.js b/src/components/Home/Analytics&Reporting/SalesByLocation.js new file mode 100644 index 0000000..94b19b3 --- /dev/null +++ b/src/components/Home/Analytics&Reporting/SalesByLocation.js @@ -0,0 +1,124 @@ +import React from 'react'; +import { + Box, + Typography, + Paper, + List, + ListItem, + ListItemText, + ListItemSecondaryAction, + Chip, + IconButton, + useTheme, + useMediaQuery +} from '@mui/material'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +const SalesByLocation = ({ data }) => { + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + + return ( + + + + + Sales by Location + + + Sales performance by location + + + + + + + + + {data.map((item, i) => ( + + + {item.country} + + } + secondary={ + + {item.sales} Sales + + } + sx={{ my: 0 }} + /> + + + ${item.amount.toLocaleString()} + + 0 ? '+' : ''}${item.change}%`} + color={item.change > 0 ? 'success' : item.change < 0 ? 'error' : 'default'} + size={isSmallScreen ? 'small' : 'medium'} + sx={{ + fontSize: { xs: '11px', sm: '12px' }, + height: { xs: '24px', sm: '28px' }, + '& .MuiChip-label': { + px: { xs: 0.5, sm: 1 } + } + }} + /> + + + ))} + + + ); +}; + +export default SalesByLocation; \ No newline at end of file diff --git a/src/components/Home/Analytics&Reporting/StatisticsCard.js b/src/components/Home/Analytics&Reporting/StatisticsCard.js new file mode 100644 index 0000000..7a27ec6 --- /dev/null +++ b/src/components/Home/Analytics&Reporting/StatisticsCard.js @@ -0,0 +1,168 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { + Box, + IconButton, + Paper, + Typography, + useTheme, + useMediaQuery +} from '@mui/material'; +import { + AreaChart, + Area, + XAxis, + YAxis, + Tooltip, + Legend, + ResponsiveContainer, + CartesianGrid +} from 'recharts'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; + +const formatCurrency = (value) => { + if (value >= 1000000) return `$${(value / 1000000).toFixed(1)}M`; + if (value >= 1000) return `$${(value / 1000).toFixed(1)}K`; + return `$${value}`; +}; + +const StatisticsCard = ({ + title = "Statistics", + subtitle = "Delivery Times", + data = [], + dataKeys = [ + { key: 'revenue', name: 'Revenue', color: '#E46A11' }, // << هنا تغيير اللون + { key: 'sales', name: 'Sales', color: '#0182FC' } // << وهنا أيضاً + ], + xDataKey = 'month', + valueFormatter = formatCurrency, + timeFrame = 'month', + onTimeFrameChange +}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md')); + + const handleTimeFrameChange = (newTimeFrame) => { + if (onTimeFrameChange) onTimeFrameChange(newTimeFrame); + }; + + return ( + + + + + + + {/* Header */} + + + + {title} + + + {subtitle} + + + + + {/* Chart */} + + + + {dataKeys.map(({ key, color }) => ( + + + + + ))} + + + + + + + + {dataKeys.map(({ key, name, color }) => ( + + ))} + + + + + ); +}; + +StatisticsCard.propTypes = { + title: PropTypes.string, + subtitle: PropTypes.string, + data: PropTypes.arrayOf(PropTypes.object), + dataKeys: PropTypes.arrayOf(PropTypes.shape({ + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + color: PropTypes.string.isRequired + })), + xDataKey: PropTypes.string, + valueFormatter: PropTypes.func, + timeFrame: PropTypes.oneOf(['day', 'week', 'month', 'year']), + onTimeFrameChange: PropTypes.func +}; + +export default StatisticsCard; diff --git a/src/components/Home/Analytics&Reporting/TimeFrameSelector.js b/src/components/Home/Analytics&Reporting/TimeFrameSelector.js new file mode 100644 index 0000000..e106c30 --- /dev/null +++ b/src/components/Home/Analytics&Reporting/TimeFrameSelector.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { Button, Stack } from '@mui/material'; + +const options = ['All Time', '12 Months', '30 Days', '7 Days', '24 Hour']; + +const TimeFrameSelector = ({ selected, onChange }) => ( + + {options.map(option => ( + + ))} + +); + +export default TimeFrameSelector; diff --git a/src/components/Home/Analytics&Reporting/TopSellingProduct.js b/src/components/Home/Analytics&Reporting/TopSellingProduct.js new file mode 100644 index 0000000..915ed77 --- /dev/null +++ b/src/components/Home/Analytics&Reporting/TopSellingProduct.js @@ -0,0 +1,215 @@ +import React, { useState } from 'react'; +import { useTheme } from '@mui/material/styles'; +import { useMediaQuery } from '@mui/material'; +import { + Box, + Typography, + Paper, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + Chip, + Pagination, + Button, + Avatar, + TableContainer +} from '@mui/material'; +import TuneIcon from '@mui/icons-material/Tune'; +import { green } from '@mui/material/colors'; +import AssignmentIcon from '@mui/icons-material/Assignment'; + +const TopSellingProduct = ({ data = [] }) => { + const theme = useTheme(); + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 5; + + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + + const pageCount = Math.ceil(data.length / itemsPerPage); + const paginatedData = data.slice( + (currentPage - 1) * itemsPerPage, + currentPage * itemsPerPage + ); + + return ( + + {/* العنوان وزر الفلاتر */} + + + Top Selling Product + + + + + {/* جدول البيانات */} + + + + + Product + {!isMobile && Sales} + Amount + {!isMobile && Price} + Status + + + + {paginatedData.map((row, i) => ( + + + + + + + + {row.product} + + + + {!isMobile && {row.sales}} + ${row.amount.toLocaleString()} + {!isMobile && ${row.price}} + + + + + ))} + +
+
+ + {/* التذييل مع الترقيم */} + + + Showing {(currentPage - 1) * itemsPerPage + 1} to {Math.min(currentPage * itemsPerPage, data.length)} of {data.length} + + + setCurrentPage(value)} + size={isMobile ? 'small' : 'medium'} + sx={{ + '& .MuiPaginationItem-root': { + fontSize: { xs: '12px', sm: '14px' }, + minWidth: { xs: 24, sm: 32 }, + height: { xs: 24, sm: 32 }, + backgroundColor: '#FFECE0', + color: theme.palette.primary.main, + borderRadius: '8px', + '&.Mui-selected': { + backgroundColor: '#FFB088', + color: '#fff', + }, + '&:hover': { + backgroundColor: '#FFD6B5', + }, + }, + }} + /> + +
+ ); +}; + +export default TopSellingProduct; diff --git a/src/components/Home/AppBar.js b/src/components/Home/AppBar.js new file mode 100644 index 0000000..b4ca373 --- /dev/null +++ b/src/components/Home/AppBar.js @@ -0,0 +1,210 @@ +import React from 'react'; +import { + AppBar, + Toolbar, + Typography, + Box, + IconButton, + Divider, + Avatar, + Button, + Autocomplete, + TextField, + InputAdornment, + useTheme, + useMediaQuery, +} from '@mui/material'; +import { useLocation } from 'react-router-dom'; +import MenuIcon from '@mui/icons-material/Menu'; +import NotificationsOutlinedIcon from '@mui/icons-material/NotificationsOutlined'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import SearchIcon from '@mui/icons-material/Search'; + +const top100Films = [ + { title: 'The Shawshank Redemption' }, + { title: 'The Godfather' }, + { title: 'The Dark Knight' }, + { title: 'Pulp Fiction' }, +]; + +const KitchPlusAppBar = ({ onDrawerToggle, sidebarOpen, isMobile }) => { + const location = useLocation(); + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + const isMediumScreen = useMediaQuery(theme.breakpoints.between('sm', 'md')); + + return ( + + + {/* Left side with toggle button */} + + {/* Toggle button for mobile/tablet */} + {(isMobile || isMediumScreen) && ( + + + + )} + + {location.pathname === '/dashboard' ? ( + + Welcome to KitchPlus + + ) : ( + option.title)} + renderInput={(params) => ( + + + + ), + }} + sx={{ + '& .MuiInputBase-root': { + backgroundColor: 'white', + height: { xs: 36, sm: 38, md: 40 }, + }, + }} + /> + )} + /> + )} + + + {/* Right side */} + + {location.pathname === '/dashboard' && !isSmallScreen && ( + + )} + {location.pathname === '/dashboard' && ( + + )} + + + + + + + + + {!isSmallScreen && ( + + Admin@gmail.com + + )} + + + + + + + + ); +}; + +export default KitchPlusAppBar; \ No newline at end of file diff --git a/src/components/Home/Cashier/Cashier.js b/src/components/Home/Cashier/Cashier.js new file mode 100644 index 0000000..ab11add --- /dev/null +++ b/src/components/Home/Cashier/Cashier.js @@ -0,0 +1,105 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const Cashier = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي) + useEffect(() => { + // هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات + // مثلاً استدعاء API أو التحقق من state + const checkProducts = async () => { + // محاكاة لاستدعاء API + const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + // دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي) + const checkIfProductsExist = async () => { + // محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state + // return true; + return false; // غير هذه القيمة حسب منطقك + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + Cashier + + + ); +}; + +export default Cashier; \ No newline at end of file diff --git a/src/components/Home/CreateYourRestaurant/CreateRestaurant.js b/src/components/Home/CreateYourRestaurant/CreateRestaurant.js new file mode 100644 index 0000000..dda8366 --- /dev/null +++ b/src/components/Home/CreateYourRestaurant/CreateRestaurant.js @@ -0,0 +1,105 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const CreateRestaurant = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي) + useEffect(() => { + // هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات + // مثلاً استدعاء API أو التحقق من state + const checkProducts = async () => { + // محاكاة لاستدعاء API + const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + // دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي) + const checkIfProductsExist = async () => { + // محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state + // return true; + return false; // غير هذه القيمة حسب منطقك + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + CreateYourRestaurant + + + ); +}; + +export default CreateRestaurant; \ No newline at end of file diff --git a/src/components/Home/Dashboard/Dashboard.js b/src/components/Home/Dashboard/Dashboard.js new file mode 100644 index 0000000..7969b6a --- /dev/null +++ b/src/components/Home/Dashboard/Dashboard.js @@ -0,0 +1,107 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; +import DashbordContect from './DashboardContcet'; +import NoProdectDash from './NoProdectDash'; + +const drawerWidth = 230; + +const Dashboard = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة التحقق من المنتجات + useEffect(() => { + const checkProducts = async () => { + setIsLoading(true); + const productsExist = await checkIfProductsExist(); // استبدل بمنطقك + setHasProducts(productsExist); + setIsLoading(false); + }; + + checkProducts(); + }, []); + + const checkIfProductsExist = async () => { + return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + + + {isLoading ? ( + <> + + + + + ) : ( + hasProducts ? : + )} + + + + ); +}; + +export default Dashboard; diff --git a/src/components/Home/Dashboard/DashboardContcet.js b/src/components/Home/Dashboard/DashboardContcet.js new file mode 100644 index 0000000..39977bf --- /dev/null +++ b/src/components/Home/Dashboard/DashboardContcet.js @@ -0,0 +1,395 @@ +import React from 'react'; +import { Box, Button, Card, CardContent, Stack, Typography, useMediaQuery } from '@mui/material'; +import AirportShuttleIcon from '@mui/icons-material/AirportShuttle'; +import CampaignIcon from '@mui/icons-material/Campaign'; +import Inventory2Icon from '@mui/icons-material/Inventory2'; +import DeveloperBoardIcon from '@mui/icons-material/DeveloperBoard'; +import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward'; +import { useTheme } from '@mui/material/styles'; +import AddIcon from '@mui/icons-material/Add'; +import OrderStatusCard from './OrderStatusCard'; +import StatisticsCard from './StatisticsCard'; +import RecentActivity from './RecentActivity'; + +const IconCircle = ({ children, bgColor = '#DEDEFA', outerColor = '#EFEFFD' }) => ( + + + + {children} + + +); + +const StatusCard = ({ + icon, + statusText, + statusColor, + iconColor, + outerColor, + innerColor, + height = { + xs: 'calc(140px + 0.5vh)', + sm: 'calc(150px + 0.5vh)', + md: 'calc(162px + 0.5vh)' + }, + width = { + xs: 'min(90%, 600px)', // تقليل من 90% إلى 85% والحد الأقصى من 300px إلى 280px + sm: 'clamp(220px, 23vw, 280px)', // تقليل جميع القيم + md: 'clamp(220px, 19vw, 300px)' + }, + transition = 'width 0.3s ease', + iconSpacing = { xs: 6, sm: 8, md: 12 }, + extraButton, + statusButtonWidth, + title = 'Point Of Sale', +}) => { + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + + return ( + + + + + {React.cloneElement(icon, { sx: { color: iconColor, fontSize: { xs: 16, sm: 18, md: 20 } } })} + + + + + + {title} + + + + {extraButton ? extraButton : } + + + + + ); +}; + +const DashboardContect = () => { + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + const isMediumScreen = useMediaQuery(theme.breakpoints.between('sm', 'md')); + + return ( + <> + {/* Header Section */} + + {/* Title */} + + Dashboard + + + {/* Buttons */} + + + + + + + + {/* Status Cards */} + + } + statusText="Active" + statusColor="#0D894F" + iconColor="#057DEC" + innerColor="#DEDEFA" + outerColor="#EFEFFD" + iconSpacing={{ xs: 6, sm: 8, md: 12 }} + extraButton={ + + } + /> + } + statusText="Active" + statusColor="#0D894F" + iconColor="#34B405" + innerColor="#E1F6DF" + outerColor="#EDFBE9" + iconSpacing={{ xs: 6, sm: 8, md: 12 }} + title="Inventory" + /> + } + statusText="Pending" + statusColor="#BBB50F" + iconColor="#990463" + innerColor="#FEC8EA" + outerColor="#FFE3F5" + iconSpacing={{ xs: 6, sm: 8, md: 12 }} + title="Marketing" + /> + } + statusText="Action Need" + statusColor="#EF0A0A" + iconColor="#069797" + outerColor="#DBFBFB" + innerColor="#B5F5F5" + iconSpacing={{ xs: 3, sm: 5, md: 7 }} + title="Delivery" + /> + + + {/* OrderStatusCard/ StatisticsCard */} + + {/* OrderStatusCard */} + + + + + {/* StatisticsCard */} + + + + + + + {/* RecentActivity */} + + + + + ); +}; + +export default DashboardContect; diff --git a/src/components/Home/Dashboard/NoProdectDash.js b/src/components/Home/Dashboard/NoProdectDash.js new file mode 100644 index 0000000..e82c6ad --- /dev/null +++ b/src/components/Home/Dashboard/NoProdectDash.js @@ -0,0 +1,109 @@ +import React from 'react'; +import { + Box, + Button, + Card, + CardContent, + Typography, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; +import AddIcon from '@mui/icons-material/Add'; + +const NoProdectDash = () => { + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + + return ( + <> + {/* Header Section */} + + + Dashboard + + + + {/* Empty State Content */} + + + {/* Image Placeholder */} + + + {/* Title with colored "Sorry!" */} + + Sorry!{' '} + There is no campaign available. + Please initiate the {'\n'}creation of a new campaign. + + + {/* Action Button */} + {/* */} + + + + ); +}; + +export default NoProdectDash; \ No newline at end of file diff --git a/src/components/Home/Dashboard/OrderStatusCard.js b/src/components/Home/Dashboard/OrderStatusCard.js new file mode 100644 index 0000000..b672730 --- /dev/null +++ b/src/components/Home/Dashboard/OrderStatusCard.js @@ -0,0 +1,260 @@ +import React from 'react'; +import { + Box, + Typography, + Card, + CardContent, + Divider, + Chip, + useTheme, + IconButton, + useMediaQuery +} from '@mui/material'; +import { + TrendingUp as TrendingUpIcon, + TrendingDown as TrendingDownIcon, + CheckCircle as CheckCircleIcon, + Cancel as CancelIcon, + Pending as PendingIcon +} from '@mui/icons-material'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import { + CircularProgressbar, + buildStyles +} from 'react-circular-progressbar'; +import 'react-circular-progressbar/dist/styles.css'; +import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; +import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; +// import { Box, IconButton, Paper, Typography, useTheme, useMediaQuery } from '@mui/material'; +import { + + ResponsiveContainer, + +} from 'recharts'; + + +const OrderStatusCard = ({ + title = 'Order Status', + period = 'This Quarter', + progress = 70.5, + progressChange = '+10%', + progressDirection = 'up', // or 'down' + description = 'You succeeded in earning $240 today, it’s higher than yesterday', + completed = '$20k', + canceled = '$16k', + pending = '$1.5k' +}) => { + const theme = useTheme(); + + const progressColor = progressDirection === 'up' ? theme.palette.success.main : theme.palette.error.main; + const progressIcon = progressDirection === 'up' ? : ; + const highlightedDescription = description.replace( + /(\$\d+(?:\.\d+)?[kKmM]?)/g, + '$1' + ); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md')); + + + return ( + + + {/* زر الإجراءات في الزاوية العلوية اليمنى */} + + + + + + {/* Header */} + + + {title} + + + {period} + + + + {/* Progress Circle */} + + {/* تغيير النسبة تحت الدائرة */} + + + + + {/* دائرة التقدم */} + + + + + + + {/* النص داخل الدائرة */} + + {`${progress}%`} + + + + + {/* الوصف */} + + + + + {/* الحقول الثلاثة (Completed / Canceled / Pending) */} + + {/* لكل قسم: */} + {[{ + label: 'Completed', + icon: , + value: completed + }, { + label: 'Canceled', + icon: , + value: canceled + }, { + label: 'Pending', + icon: , + value: pending + }].map(({ label, icon, value }, i) => ( + + + {label} + + + {icon} + + {value} + + + + ))} + + + + + ); +}; + +export default OrderStatusCard; diff --git a/src/components/Home/Dashboard/RecentActivity.js b/src/components/Home/Dashboard/RecentActivity.js new file mode 100644 index 0000000..f24b20f --- /dev/null +++ b/src/components/Home/Dashboard/RecentActivity.js @@ -0,0 +1,107 @@ +import React from 'react'; +import { + Box, + Typography, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Button, + Chip +} from '@mui/material'; +// import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +// import InventoryIcon from '@mui/icons-material/Inventory'; +// import AssignmentIcon from '@mui/icons-material/Assignment'; + +const RecentActivity = () => { + // Sample data + const activities = [ + { + id: 1, + order: 'Order #1234 completed', + delivery: 'Delivery en route', + inventory: 'Low stock on item #567' + }, + { + id: 2, + order: 'Order #1235 completed', + delivery: 'Delivery delayed', + inventory: 'Low stock on item #890' + }, + { + id: 3, + order: 'Order #1236 completed', + delivery: 'Delivery arrived', + inventory: 'Out of stock on item #123' + } + ]; + + return ( + + + Recent Activity + + + + + + + + New Orders + Delivery Updates + Inventory Alerts + Actions + + + + {activities.map((activity) => ( + + + + {activity.order} + + + + + + {activity.delivery} + + + + + + {activity.inventory} + + + + + + + + + + + ))} + +
+
+
+ ); +}; + +export default RecentActivity; \ No newline at end of file diff --git a/src/components/Home/Dashboard/StatisticsCard.js b/src/components/Home/Dashboard/StatisticsCard.js new file mode 100644 index 0000000..24874b1 --- /dev/null +++ b/src/components/Home/Dashboard/StatisticsCard.js @@ -0,0 +1,196 @@ +import React from 'react'; +import { Box, IconButton, Paper, Typography, useTheme, useMediaQuery } from '@mui/material'; +import { + LineChart, + Line, + XAxis, + YAxis, + Tooltip, + Legend, + ResponsiveContainer, + Area, + AreaChart, + CartesianGrid, + defs, + linearGradient, + stop +} from 'recharts'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; + +const data = [ + { month: 'Jan', revenue: 4000, sales: 2400 }, + { month: 'Feb', revenue: 3000, sales: 1398 }, + { month: 'Mar', revenue: 2000, sales: 9800 }, + { month: 'Apr', revenue: 2780, sales: 3908 }, + { month: 'May', revenue: 1890, sales: 4800 }, + { month: 'Jun', revenue: 2390, sales: 3800 }, + { month: 'Jul', revenue: 3490, sales: 4300 }, + { month: 'Aug', revenue: 5000, sales: 4000 }, + { month: 'Sep', revenue: 4700, sales: 4200 }, + { month: 'Oct', revenue: 5200, sales: 4600 }, + { month: 'Nov', revenue: 4800, sales: 4400 }, + { month: 'Dec', revenue: 5300, sales: 4800 }, +]; + +const formatCurrency = (value) => { + if (value >= 1000000) { + return `$${(value / 1000000).toFixed(1)}M`; + } else if (value >= 1000) { + return `$${(value / 1000).toFixed(1)}K`; + } + return `$${value}`; +}; + +const StatisticsCard = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md')); + + return ( + + + + + + + + + Statistics + + + Delivery Times + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default StatisticsCard; \ No newline at end of file diff --git a/src/components/Home/HostKitchen/HostKitchen.js b/src/components/Home/HostKitchen/HostKitchen.js new file mode 100644 index 0000000..11be5cf --- /dev/null +++ b/src/components/Home/HostKitchen/HostKitchen.js @@ -0,0 +1,103 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const HostKitchen = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + + useEffect(() => { + const checkProducts = async () => { + + const productsExist = await checkIfProductsExist(); + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + // دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي) + const checkIfProductsExist = async () => { + // محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state + // return true; + return false; // غير هذه القيمة حسب منطقك + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + HostKitchen + + + ); +}; + +export default HostKitchen; \ No newline at end of file diff --git a/src/components/Home/Inventory/Inventory.js b/src/components/Home/Inventory/Inventory.js new file mode 100644 index 0000000..d9b8cd0 --- /dev/null +++ b/src/components/Home/Inventory/Inventory.js @@ -0,0 +1,105 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const Inventory = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي) + useEffect(() => { + // هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات + // مثلاً استدعاء API أو التحقق من state + const checkProducts = async () => { + // محاكاة لاستدعاء API + const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + // دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي) + const checkIfProductsExist = async () => { + // محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state + // return true; + return false; // غير هذه القيمة حسب منطقك + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + Inventory + + + ); +}; + +export default Inventory; \ No newline at end of file diff --git a/src/components/Home/RestaurantProfile/RestaurantProfile.js b/src/components/Home/RestaurantProfile/RestaurantProfile.js new file mode 100644 index 0000000..020a5b9 --- /dev/null +++ b/src/components/Home/RestaurantProfile/RestaurantProfile.js @@ -0,0 +1,105 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const RestaurantProfile = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي) + useEffect(() => { + // هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات + // مثلاً استدعاء API أو التحقق من state + const checkProducts = async () => { + // محاكاة لاستدعاء API + const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + // دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي) + const checkIfProductsExist = async () => { + // محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state + // return true; + return false; // غير هذه القيمة حسب منطقك + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + RestaurantProfile + + + ); +}; + +export default RestaurantProfile; \ No newline at end of file diff --git a/src/components/Home/Settings/Setting.js b/src/components/Home/Settings/Setting.js new file mode 100644 index 0000000..e717d83 --- /dev/null +++ b/src/components/Home/Settings/Setting.js @@ -0,0 +1,101 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const Setting = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + + useEffect(() => { + const checkProducts = async () => { + + const productsExist = await checkIfProductsExist(); + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + + const checkIfProductsExist = async () => { + return false; + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + Setting + + + ); +}; + +export default Setting; \ No newline at end of file diff --git a/src/components/Home/SideHome.js b/src/components/Home/SideHome.js new file mode 100644 index 0000000..e268361 --- /dev/null +++ b/src/components/Home/SideHome.js @@ -0,0 +1,207 @@ +import React from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; +import { + Drawer, + List, + ListItem, + ListItemIcon, + ListItemText, + Box, + useTheme, + Typography +} from '@mui/material'; +import { + DashboardRounded as DashboardIcon, + PointOfSale as CashierIcon, + AllInbox as SupplierIcon, + Store as InventoryIcon, + School as TrainingIcon, + AutoGraph as AnalyticsIcon, + Restaurant as RestaurantIcon, + CountertopsTwoTone as HostKitchenIcon, + Queue as CreateKitchenIcon, + Settings as SettingsIcon, + Logout as LogoutIcon +} from '@mui/icons-material'; + +const menuItems = [ + { text: 'Dashboard', icon: , path: '/dashboard' }, + { text: 'Cashier', icon: , path: '/cashier' }, + { text: 'Supplier', icon: , path: '/supplier' }, + { text: 'Inventory', icon: , path: '/inventory' }, + { text: 'Training', icon: , path: '/training' }, + { text: 'Analytics & Reporting', icon: , path: '/analytics' }, + { text: 'Restaurant Profile', icon: , path: '/profile' }, + { text: 'Host Kitchen', icon: , path: '/host-kitchen' }, + { text: 'Create Kitchen', icon: , path: '/create-kitchen' }, + +]; + +const bottomItems = [ + { text: 'Settings', icon: , path: '/settings' }, + { text: 'Log Out', icon: , path: '/login' }, +]; + +const Sidebar = ({ open, onClose, isMobile, drawerWidth }) => { + const theme = useTheme(); + const navigate = useNavigate(); + const location = useLocation(); + + const renderListItems = (items) => + items.map((item, index) => { + const isActive = location.pathname === item.path; + + return ( + + { + if (item.text === 'Log Out') { + localStorage.removeItem('token'); + } + navigate(item.path); + if (isMobile) onClose(); + }} + sx={{ + display: 'flex', + alignItems: 'center', + width: '100%', + borderRadius: '5px', + backgroundColor: isActive ? '#F8F6F8' : 'transparent', + px: 2, + py: 1, + cursor: 'pointer', + transition: 'background-color 0.2s', + '&:hover': { + backgroundColor: '#fffcf9d5', + }, + }} + > + + {item.icon} + + + + + ); + }); + + const drawer = ( + + + + + + + KITCH + + + PLUS + + + + + + + {renderListItems(menuItems)} + + + + {renderListItems(bottomItems)} + + + ); + + return ( + + + {drawer} + + + + ); + +}; + +export default Sidebar; diff --git a/src/components/Home/Supplier/Supplier.js b/src/components/Home/Supplier/Supplier.js new file mode 100644 index 0000000..76ef908 --- /dev/null +++ b/src/components/Home/Supplier/Supplier.js @@ -0,0 +1,102 @@ + +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Typography } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +const drawerWidth = 230; + +const Supplier = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + + useEffect(() => { + const checkProducts = async () => { + + const productsExist = await checkIfProductsExist(); + setHasProducts(productsExist); + }; + + checkProducts(); + }, []); + + + const checkIfProductsExist = async () => { + return false; + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + Supplier + + + ); +}; + +export default Supplier; \ No newline at end of file diff --git a/src/components/Home/Training/NoTraining.js b/src/components/Home/Training/NoTraining.js new file mode 100644 index 0000000..c02c2d9 --- /dev/null +++ b/src/components/Home/Training/NoTraining.js @@ -0,0 +1,95 @@ +import React from 'react'; +import { + Box, + Button, + Card, + CardContent, + Typography, + useMediaQuery +} from '@mui/material'; +import { useTheme } from '@mui/material/styles'; + + +const NoTraining = () => { + const theme = useTheme(); + const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + + return ( + <> + {/* Header Section */} + + + Dashboard + + + + {/* Empty State Content */} + + + {/* Image Placeholder */} + + + {/* Title with colored "Sorry!" */} + + Sorry!{' '} + There are no updates now.. + {'\n'}check back later. + + + {/* Action Button */} + + + + + ); +}; + +export default NoTraining; \ No newline at end of file diff --git a/src/components/Home/Training/Training.js b/src/components/Home/Training/Training.js new file mode 100644 index 0000000..1877735 --- /dev/null +++ b/src/components/Home/Training/Training.js @@ -0,0 +1,107 @@ +import React, { useState, useEffect } from 'react'; +import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material'; +import KitchPlusAppBar from '../AppBar'; +import Sidebar from '../SideHome'; + +import NoTraining from './NoTraining'; + +const drawerWidth = 230; + +const Dashboard = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const [hasProducts, setHasProducts] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState(!isMobile); + + // محاكاة التحقق من المنتجات + useEffect(() => { + const checkProducts = async () => { + setIsLoading(true); + const productsExist = await checkIfProductsExist(); // استبدل بمنطقك + setHasProducts(productsExist); + setIsLoading(false); + }; + + checkProducts(); + }, []); + + const checkIfProductsExist = async () => { + return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير + }; + + useEffect(() => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }, [theme.breakpoints.values.md]); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth >= theme.breakpoints.values.md) { + setSidebarOpen(true); + } else { + setSidebarOpen(false); + } + }; + + handleResize(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [theme.breakpoints.values.md]); + + const handleDrawerToggle = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( + + + + + + + + {isLoading ? ( + <> + + + + + ) : ( + + )} + + + + ); +}; + +export default Dashboard; diff --git a/src/test.js b/src/test.js new file mode 100644 index 0000000..b28e130 --- /dev/null +++ b/src/test.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTheme } from '@mui/material/styles'; +import { Box, Typography } from '@mui/material'; + +const Test = () => { // لاحظ الحرف الكبير في بداية الاسم + const navigate = useNavigate(); // صحيح الآن لأنها داخل مكون React + const theme = useTheme(); // تعريف theme باستخدام useTheme + + const handleClick = () => { + navigate('/dashboard'); + }; + + return ( + + + Test Component + + + + ); +}; + +export default Test; \ No newline at end of file diff --git a/src/theme.js b/src/theme.js new file mode 100644 index 0000000..689e8d9 --- /dev/null +++ b/src/theme.js @@ -0,0 +1,24 @@ +import { createTheme } from '@mui/material/styles'; + +const theme = createTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 900, + lg: 1200, + xl: 1536, + }, + }, + typography: { + fontFamily: 'INTER', + }, + palette: { + primary: { + main: '#FF914D', // ← اللون الأساسي الجديد + hover: '#e57f3f' + }, + }, +}); + +export default theme;