diff --git a/.env b/.env
new file mode 100644
index 0000000..e69de29
diff --git a/.eslintrc.json b/.eslintrc.json
index e0c2427..5f7de28 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -2,6 +2,8 @@
"env": {
"node": true
},
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint"],
"extends": [
// By extending from a plugin config, we can get recommended rules without having to add them manually.
"eslint:recommended",
@@ -31,6 +33,9 @@
// Add your own rules here to override ones from the extended configs.
"react/react-in-jsx-scope": "off",
"@typescript-eslint/no-empty-function": "off",
- "@typescript-eslint/no-explicit-any": "off"
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-empty-interface": "off",
+ "react/prop-types": "off",
+ "jsx-a11y/no-autofocus": "off"
}
}
diff --git a/README.md b/README.md
index c7cbe33..1333ed7 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1 @@
-# Project structure 🏗
-
-I've used this architecture on multiple larger projects in the past and it performed really well.
-
-There are two special root folders in `src`: `App` and `shared` (described below). All other root folders in `src` (in our case only two: `Auth` and `Project`) should follow the structure of the routes. We can call these folders modules.
-
-The main rule to follow: **Files from one module can only import from ancestor folders within the same module or from `src/shared`.** This makes the codebase easier to understand, and if you're fiddling with code in one module, you will never introduce a bug in another module.
-
-
-
-| File or folder | Description |
-| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `src/index.jsx` | The entry file. This is where we import babel polyfills and render the App into the root DOM node. |
-| `src/index.html` | The only HTML file in our App. All scripts and styles will be injected here by Webpack. |
-| `src/App` | Main application routes, components that need to be mounted at all times regardless of current route, global css styles, fonts, etc. Basically anything considered global / ancestor of all modules. |
-| `src/Auth` | Authentication module |
-| `src/Project` | Project module |
-| `src/shared` | Components, constants, utils, hooks, styles etc. that can be used anywhere in the codebase. Any module is allowed to import from shared. |
+TODO
diff --git a/package-lock.json b/package-lock.json
index 229aa8e..734f123 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -343,6 +343,67 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@date-io/core": {
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.16.0.tgz",
+ "integrity": "sha512-DYmSzkr+jToahwWrsiRA2/pzMEtz9Bq1euJwoOuYwuwIYXnZFtHajY2E6a1VNVDc9jP8YUXK1BvnZH9mmT19Zg=="
+ },
+ "@date-io/date-fns": {
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-2.16.0.tgz",
+ "integrity": "sha512-bfm5FJjucqlrnQcXDVU5RD+nlGmL3iWgkHTq3uAZWVIuBu6dDmGa3m8a6zo2VQQpu8ambq9H22UyUpn7590joA==",
+ "requires": {
+ "@date-io/core": "^2.16.0"
+ }
+ },
+ "@date-io/date-fns-jalali": {
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@date-io/date-fns-jalali/-/date-fns-jalali-2.16.0.tgz",
+ "integrity": "sha512-MNVvGYwRiBydbvY7gvZM14W2kosIG29G1Ekw5qmYWOXkIIFngh6ZvV7/uVGDCW+gqlIeSz/XitZXA9n8RO0tJw==",
+ "requires": {
+ "@date-io/core": "^2.16.0"
+ }
+ },
+ "@date-io/dayjs": {
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@date-io/dayjs/-/dayjs-2.16.0.tgz",
+ "integrity": "sha512-y5qKyX2j/HG3zMvIxTobYZRGnd1FUW2olZLS0vTj7bEkBQkjd2RO7/FEwDY03Z1geVGlXKnzIATEVBVaGzV4Iw==",
+ "requires": {
+ "@date-io/core": "^2.16.0"
+ }
+ },
+ "@date-io/hijri": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@date-io/hijri/-/hijri-2.16.1.tgz",
+ "integrity": "sha512-6BxY0mtnqj5cBiXluRs3uWN0mSJwGw0AB2ZxqtEHvBFoiSYEojW51AETnfPIWpdvDsBn+WAC7QrfBvQZnoyIkQ==",
+ "requires": {
+ "@date-io/moment": "^2.16.1"
+ }
+ },
+ "@date-io/jalaali": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@date-io/jalaali/-/jalaali-2.16.1.tgz",
+ "integrity": "sha512-GLw87G/WJ1DNrQHW8p/LqkqAqTUSqBSRin0H1pRPwCccB5Fh7GT64sadjzEvjW56lPJ0aq2vp5yI2eIjZajfrw==",
+ "requires": {
+ "@date-io/moment": "^2.16.1"
+ }
+ },
+ "@date-io/luxon": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@date-io/luxon/-/luxon-2.16.1.tgz",
+ "integrity": "sha512-aeYp5K9PSHV28946pC+9UKUi/xMMYoaGelrpDibZSgHu2VWHXrr7zWLEr+pMPThSs5vt8Ei365PO+84pCm37WQ==",
+ "requires": {
+ "@date-io/core": "^2.16.0"
+ }
+ },
+ "@date-io/moment": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-2.16.1.tgz",
+ "integrity": "sha512-JkxldQxUqZBfZtsaCcCMkm/dmytdyq5pS1RxshCQ4fHhsvP5A7gSqPD22QbVXMcJydi3d3v1Y8BQdUKEuGACZQ==",
+ "requires": {
+ "@date-io/core": "^2.16.0"
+ }
+ },
"@emotion/babel-plugin": {
"version": "11.10.6",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz",
@@ -651,6 +712,406 @@
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
"dev": true
},
+ "@firebase/analytics": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.9.4.tgz",
+ "integrity": "sha512-Mb2UaD0cyJ9DrTk4Okz8wqpjZuVRVXHZOjhbQcmGb8VtibXY1+jm/k3eJ21r7NqUKnjWejYM2EX+hI9+dtXGkQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.4.tgz",
+ "integrity": "sha512-ZN4K49QwOR8EWIUTV03VBdcVkz8sVsfJmve4g2+FEIj0kyTK0MdoVTWNOwWj9TVi2p/7FvKRKkpWxkydmi9x7g==",
+ "requires": {
+ "@firebase/analytics": "0.9.4",
+ "@firebase/analytics-types": "0.8.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz",
+ "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw=="
+ },
+ "@firebase/app": {
+ "version": "0.9.5",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.5.tgz",
+ "integrity": "sha512-mXO9hrygxCohD8Qy0z8p9ZtuQirmjkjSTuQghH05/kLG1UJqP0TQZBlhP5qwzMTKuu2YpIn3kX2PZoSWti8LDA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.6.4.tgz",
+ "integrity": "sha512-M9qyVTWkEkHXmgwGtObvXQqKcOe9iKAOPqm0pCe74mzgKVTNq157ff39+fxHPb4nFbipToY+GuvtabLUzkHehQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-compat": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.4.tgz",
+ "integrity": "sha512-s6ON0ixPKe99M1DNYMI2eR5aLwQZgy0z8fuW1tnEbzg5p/N/GKFmqiIHSV4gfp8+X7Fw5NLm7qMfh4xrcPgQCw==",
+ "requires": {
+ "@firebase/app-check": "0.6.4",
+ "@firebase/app-check-types": "0.5.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-interop-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.2.0.tgz",
+ "integrity": "sha512-+3PQIeX6/eiVK+x/yg8r6xTNR97fN7MahFDm+jiQmDjcyvSefoGuTTNQuuMScGyx3vYUBeZn+Cp9kC0yY/9uxQ=="
+ },
+ "@firebase/app-check-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz",
+ "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ=="
+ },
+ "@firebase/app-compat": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.5.tgz",
+ "integrity": "sha512-PSEax7UAc1Qxcksq5GHKb8M9rCsXTJWxWUf6pqhGTWO9UbJnI1tv00ogoCicEHgkXBTkOWMLxCs3318HaGZh4g==",
+ "requires": {
+ "@firebase/app": "0.9.5",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-types": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz",
+ "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q=="
+ },
+ "@firebase/auth": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.21.5.tgz",
+ "integrity": "sha512-Pt/S24qbtJeFPxYxcQHDNgYAuEa9oyCK1XJBQ9Kc3FT1rDMb1OaK6wfnDDrCChQfENdHZVI1pGw4QG6/tO3NWw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/auth-compat": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.3.5.tgz",
+ "integrity": "sha512-xEkR4Buuw8NfyJhMVC3HMvyaODfstpMuo55tK03APoP+X9fnZpQE+ASdacq60qBBvpKF78d+gmAhmh0ISTXZ0w==",
+ "requires": {
+ "@firebase/auth": "0.21.5",
+ "@firebase/auth-types": "0.12.0",
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/auth-interop-types": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz",
+ "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg=="
+ },
+ "@firebase/auth-types": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz",
+ "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA=="
+ },
+ "@firebase/component": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz",
+ "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==",
+ "requires": {
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database": {
+ "version": "0.14.4",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz",
+ "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==",
+ "requires": {
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-compat": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz",
+ "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/database": "0.14.4",
+ "@firebase/database-types": "0.10.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-types": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz",
+ "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==",
+ "requires": {
+ "@firebase/app-types": "0.9.0",
+ "@firebase/util": "1.9.3"
+ }
+ },
+ "@firebase/firestore": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.9.0.tgz",
+ "integrity": "sha512-At8HeTec3y7EfGjtYqvzON/8896igJgE34zjEndYxKPUKyhQ6xtcM+zhfa8C+lUW6W8qQB6lNzTNNXmF4NxdpQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "@firebase/webchannel-wrapper": "0.9.0",
+ "@grpc/grpc-js": "~1.7.0",
+ "@grpc/proto-loader": "^0.6.13",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/firestore-compat": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.5.tgz",
+ "integrity": "sha512-gwBFGOqNIgF2TOJ2mKIS1lTQy6I9DytWsmIfvXGV76is53MaZUZXyUZd7oIC8h2Otq6gP3xtvPRQJTMcnQrbFg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/firestore": "3.9.0",
+ "@firebase/firestore-types": "2.5.1",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/firestore-types": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.1.tgz",
+ "integrity": "sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw=="
+ },
+ "@firebase/functions": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.9.4.tgz",
+ "integrity": "sha512-3H2qh6U+q+nepO5Hds+Ddl6J0pS+zisuBLqqQMRBHv9XpWfu0PnDHklNmE8rZ+ccTEXvBj6zjkPfdxt6NisvlQ==",
+ "requires": {
+ "@firebase/app-check-interop-types": "0.2.0",
+ "@firebase/auth-interop-types": "0.2.1",
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/functions-compat": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.4.tgz",
+ "integrity": "sha512-kxVxTGyLV1MBR3sp3mI+eQ6JBqz0G5bk310F8eX4HzDFk4xjk5xY0KdHktMH+edM2xs1BOg0vwvvsAHczIjB+w==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/functions": "0.9.4",
+ "@firebase/functions-types": "0.6.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/functions-types": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz",
+ "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw=="
+ },
+ "@firebase/installations": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz",
+ "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/installations-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.4.tgz",
+ "integrity": "sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-types": "0.5.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/installations-types": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz",
+ "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg=="
+ },
+ "@firebase/logger": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz",
+ "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.4.tgz",
+ "integrity": "sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/messaging-interop-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "idb": "7.0.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz",
+ "integrity": "sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging-interop-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz",
+ "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ=="
+ },
+ "@firebase/performance": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz",
+ "integrity": "sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.4.tgz",
+ "integrity": "sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-types": "0.2.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-types": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz",
+ "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA=="
+ },
+ "@firebase/remote-config": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz",
+ "integrity": "sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-compat": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz",
+ "integrity": "sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/logger": "0.4.0",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-types": "0.3.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-types": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz",
+ "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA=="
+ },
+ "@firebase/storage": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz",
+ "integrity": "sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/util": "1.9.3",
+ "node-fetch": "2.6.7",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/storage-compat": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.2.tgz",
+ "integrity": "sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==",
+ "requires": {
+ "@firebase/component": "0.6.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-types": "0.8.0",
+ "@firebase/util": "1.9.3",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/storage-types": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz",
+ "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg=="
+ },
+ "@firebase/util": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz",
+ "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/webchannel-wrapper": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.9.0.tgz",
+ "integrity": "sha512-BpiZLBWdLFw+qFel9p3Zs1jD6QmH7Ii4aTDu6+vx8ShdidChZUXqDhYJly4ZjSgQh54miXbBgBrk0S+jTIh/Qg=="
+ },
"@fontsource/ibm-plex-sans": {
"version": "4.5.13",
"resolved": "https://registry.npmjs.org/@fontsource/ibm-plex-sans/-/ibm-plex-sans-4.5.13.tgz",
@@ -666,6 +1127,63 @@
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz",
"integrity": "sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA=="
},
+ "@grpc/grpc-js": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.7.3.tgz",
+ "integrity": "sha512-H9l79u4kJ2PVSxUNA08HMYAnUBLj9v6KjYQ7SQ71hOZcEXhShE/y5iQCesP8+6/Ik/7i2O0a10bPquIcYfufog==",
+ "requires": {
+ "@grpc/proto-loader": "^0.7.0",
+ "@types/node": ">=12.12.47"
+ },
+ "dependencies": {
+ "@grpc/proto-loader": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.5.tgz",
+ "integrity": "sha512-mfcTuMbFowq1wh/Rn5KQl6qb95M21Prej3bewD9dUQMurYGVckGO/Pbe2Ocwto6sD05b/mxZLspvqwx60xO2Rg==",
+ "requires": {
+ "@types/long": "^4.0.1",
+ "lodash.camelcase": "^4.3.0",
+ "long": "^4.0.0",
+ "protobufjs": "^7.0.0",
+ "yargs": "^16.2.0"
+ }
+ }
+ }
+ },
+ "@grpc/proto-loader": {
+ "version": "0.6.13",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz",
+ "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==",
+ "requires": {
+ "@types/long": "^4.0.1",
+ "lodash.camelcase": "^4.3.0",
+ "long": "^4.0.0",
+ "protobufjs": "^6.11.3",
+ "yargs": "^16.2.0"
+ },
+ "dependencies": {
+ "protobufjs": {
+ "version": "6.11.3",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz",
+ "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.1",
+ "@types/node": ">=13.7.0",
+ "long": "^4.0.0"
+ }
+ }
+ }
+ },
"@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
@@ -905,6 +1423,46 @@
}
}
},
+ "@mui/x-date-pickers": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.0.3.tgz",
+ "integrity": "sha512-TgKfWf47WiNzSAY3C8R+FQ2grtVveoS3WCtLf6E1I/O2adxruxXA+AFiIRVnfv8QX9QFLNayTKoaVUISg/PcXQ==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@date-io/core": "^2.16.0",
+ "@date-io/date-fns": "^2.16.0",
+ "@date-io/date-fns-jalali": "^2.16.0",
+ "@date-io/dayjs": "^2.16.0",
+ "@date-io/hijri": "^2.16.1",
+ "@date-io/jalaali": "^2.16.1",
+ "@date-io/luxon": "^2.16.1",
+ "@date-io/moment": "^2.16.1",
+ "@mui/utils": "^5.11.13",
+ "@types/react-transition-group": "^4.4.5",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "dependencies": {
+ "@mui/utils": {
+ "version": "5.11.13",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz",
+ "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@types/prop-types": "^15.7.5",
+ "@types/react-is": "^16.7.1 || ^17.0.0",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ }
+ },
+ "react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ }
+ }
+ },
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -936,11 +1494,85 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
},
+ "@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
+ },
+ "@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
+ },
+ "@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
+ },
+ "@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
+ },
+ "@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
+ },
+ "@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
+ },
+ "@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
+ },
+ "@reduxjs/toolkit": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
+ "integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
+ "requires": {
+ "immer": "^9.0.16",
+ "redux": "^4.2.0",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.7"
+ }
+ },
"@remix-run/router": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.3.tgz",
"integrity": "sha512-YRHie1yQEj0kqqCTCJEfHqYSSNlZQ696QJG+MMiW4mxSl9I0ojz/eRhJS4fs88Z5i6D1SmoF9d3K99/QOhI8/w=="
},
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -953,6 +1585,16 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
+ "@types/long": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
+ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="
+ },
+ "@types/node": {
+ "version": "18.15.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz",
+ "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw=="
+ },
"@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
@@ -1009,6 +1651,11 @@
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
"dev": true
},
+ "@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
"@typescript-eslint/eslint-plugin": {
"version": "5.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz",
@@ -1148,8 +1795,7 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "3.2.1",
@@ -1246,6 +1892,11 @@
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
"available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
@@ -1258,6 +1909,16 @@
"integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==",
"dev": true
},
+ "axios": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
+ "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+ "requires": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -1372,6 +2033,16 @@
"readdirp": "~3.6.0"
}
},
+ "cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
"clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -1390,6 +2061,14 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1444,6 +2123,11 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
+ "date-fns": {
+ "version": "2.29.3",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
+ "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
+ },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1493,6 +2177,11 @@
"object-keys": "^1.1.1"
}
},
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+ },
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -1662,8 +2351,7 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -2125,6 +2813,14 @@
"reusify": "^1.0.4"
}
},
+ "faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -2158,6 +2854,39 @@
"path-exists": "^4.0.0"
}
},
+ "firebase": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-9.18.0.tgz",
+ "integrity": "sha512-CTV5S3mTtn9zodeWkdeTqiQFyS7t+iskA50V9hVKPCQ4TPw4tnoyNgtNzWUmemFnYadzzsTnAaxsR7UaBJgiqw==",
+ "requires": {
+ "@firebase/analytics": "0.9.4",
+ "@firebase/analytics-compat": "0.2.4",
+ "@firebase/app": "0.9.5",
+ "@firebase/app-check": "0.6.4",
+ "@firebase/app-check-compat": "0.3.4",
+ "@firebase/app-compat": "0.2.5",
+ "@firebase/app-types": "0.9.0",
+ "@firebase/auth": "0.21.5",
+ "@firebase/auth-compat": "0.3.5",
+ "@firebase/database": "0.14.4",
+ "@firebase/database-compat": "0.3.4",
+ "@firebase/firestore": "3.9.0",
+ "@firebase/firestore-compat": "0.3.5",
+ "@firebase/functions": "0.9.4",
+ "@firebase/functions-compat": "0.3.4",
+ "@firebase/installations": "0.6.4",
+ "@firebase/installations-compat": "0.2.4",
+ "@firebase/messaging": "0.12.4",
+ "@firebase/messaging-compat": "0.2.4",
+ "@firebase/performance": "0.6.4",
+ "@firebase/performance-compat": "0.2.4",
+ "@firebase/remote-config": "0.4.4",
+ "@firebase/remote-config-compat": "0.2.4",
+ "@firebase/storage": "0.11.2",
+ "@firebase/storage-compat": "0.3.2",
+ "@firebase/util": "1.9.3"
+ }
+ },
"flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -2174,6 +2903,11 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
+ "follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ },
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -2183,6 +2917,16 @@
"is-callable": "^1.1.3"
}
},
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2225,6 +2969,11 @@
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true
},
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
"get-intrinsic": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
@@ -2303,6 +3052,11 @@
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true
},
+ "goober": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.12.tgz",
+ "integrity": "sha512-yXHAvO08FU1JgTXX6Zn6sYCUFfB/OJSX8HHjDSgerZHZmFKAb08cykp5LBw5QnmyMcZyPRMqkdyHUSSzge788Q=="
+ },
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -2383,17 +3137,32 @@
"react-is": "^16.7.0"
}
},
+ "http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
+ },
"hyphenate-style-name": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
},
+ "idb": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz",
+ "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg=="
+ },
"ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
+ "immer": {
+ "version": "9.0.19",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz",
+ "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ=="
+ },
"immutable": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz",
@@ -2525,6 +3294,11 @@
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -2840,12 +3614,22 @@
"p-locate": "^5.0.0"
}
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+ },
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -2888,6 +3672,19 @@
"picomatch": "^2.3.1"
}
},
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2926,6 +3723,14 @@
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
"node-releases": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz",
@@ -2938,6 +3743,15 @@
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
+ "notistack": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.1.tgz",
+ "integrity": "sha512-ntVZXXgSQH5WYfyU+3HfcXuKaapzAJ8fBLQ/G618rn3yvSzEbnOB8ZSOwhX+dAORy/lw+GC2N061JA0+gYWTVA==",
+ "requires": {
+ "clsx": "^1.1.0",
+ "goober": "^2.0.33"
+ }
+ },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -3153,6 +3967,37 @@
"react-is": "^16.13.1"
}
},
+ "protobufjs": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.2.tgz",
+ "integrity": "sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "dependencies": {
+ "long": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz",
+ "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A=="
+ }
+ }
+ },
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
@@ -3187,6 +4032,26 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "react-redux": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
+ "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
+ "requires": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ }
+ }
+ },
"react-refresh": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@@ -3230,6 +4095,19 @@
"picomatch": "^2.2.1"
}
},
+ "redux": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+ "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+ "requires": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "redux-thunk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
+ "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q=="
+ },
"regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
@@ -3252,6 +4130,16 @@
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
"dev": true
},
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+ },
+ "reselect": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
+ "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
+ },
"resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -3300,6 +4188,11 @@
"queue-microtask": "^1.2.2"
}
},
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
"safe-regex-test": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
@@ -3391,6 +4284,23 @@
"internal-slot": "^1.0.4"
}
},
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ }
+ }
+ },
"string.prototype.matchall": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -3433,7 +4343,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -3493,6 +4402,11 @@
"is-number": "^7.0.0"
}
},
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
"tsconfck": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-2.0.3.tgz",
@@ -3522,6 +4436,11 @@
}
}
},
+ "tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
+ },
"tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
@@ -3602,6 +4521,11 @@
"punycode": "^2.1.0"
}
},
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
+ },
"vite": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.1.4.tgz",
@@ -3626,6 +4550,35 @@
"tsconfck": "^2.0.1"
}
},
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "requires": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3680,12 +4633,50 @@
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true
},
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ }
+ }
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
+ },
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@@ -3697,6 +4688,25 @@
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
},
+ "yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
+ },
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 8118f80..c1e529a 100644
--- a/package.json
+++ b/package.json
@@ -20,9 +20,16 @@
"@mui/lab": "^5.0.0-alpha.122",
"@mui/material": "^5.11.12",
"@mui/styles": "^5.11.12",
+ "@mui/x-date-pickers": "^6.0.3",
+ "@reduxjs/toolkit": "^1.9.3",
+ "axios": "^1.3.4",
+ "date-fns": "^2.29.3",
+ "firebase": "^9.18.0",
"history": "^5.3.0",
+ "notistack": "^3.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-redux": "^8.0.5",
"react-router-dom": "^6.8.2"
},
"devDependencies": {
diff --git a/src/App/App.tsx b/src/App/App.tsx
index 208200f..c5a245c 100644
--- a/src/App/App.tsx
+++ b/src/App/App.tsx
@@ -1,16 +1,60 @@
-import CssBaseline from '@mui/material/CssBaseline';
+import { useEffect } from 'react';
+import { styled, CssBaseline } from '@mui/material';
import { useRoutes } from 'react-router-dom';
-import ThemeProvider from './theme/ThemeProvider';
+import { LocalizationProvider } from '@mui/x-date-pickers';
+import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
+import { useAppDispatch, useAppSelector } from './hooks';
+import { onAuthStateChanged } from 'firebase/auth';
+import { auth } from './firebase/firebaseConfig';
+import { saveUser } from 'features/auth/authSlice';
+import { SnackbarProvider, MaterialDesignContent } from 'notistack';
import router from './router';
+import ThemeProvider from './theme/ThemeProvider';
+
+const StyledSnackbarContent = styled(MaterialDesignContent)(({ theme }) => ({
+ '&.notistack-MuiContent-success': {
+ backgroundColor: theme.palette.success.main,
+ },
+ '&.notistack-MuiContent-error': {
+ backgroundColor: theme.palette.error.main,
+ },
+}));
const App = () => {
const content = useRoutes(router);
+ const user = useAppSelector((state) => state.auth.value);
+ console.log('user from state', user);
+
+ const dispatch = useAppDispatch();
+ useEffect(() => {
+ onAuthStateChanged(auth, (user) => {
+ if (user) {
+ dispatch(saveUser(user.refreshToken));
+ } else {
+ dispatch(saveUser(undefined));
+ }
+ });
+ }, [auth, dispatch]);
+
return (
-
-
- {content}
-
+
+
+
+
+ {content}
+
+
+
);
};
diff --git a/src/App/assets/404.svg b/src/App/assets/404.svg
new file mode 100644
index 0000000..9c4d4f6
--- /dev/null
+++ b/src/App/assets/404.svg
@@ -0,0 +1,64 @@
+
diff --git a/src/App/assets/undraw_wandering_mind.svg b/src/App/assets/undraw_wandering_mind.svg
new file mode 100644
index 0000000..beb3b7a
--- /dev/null
+++ b/src/App/assets/undraw_wandering_mind.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/App/axios.ts b/src/App/axios.ts
new file mode 100644
index 0000000..a46f2a0
--- /dev/null
+++ b/src/App/axios.ts
@@ -0,0 +1,22 @@
+import axios from 'axios';
+
+const token = localStorage.getItem('token');
+
+axios.interceptors.request.use(
+ (config) => {
+ if (config.method === 'post') {
+ config.headers['Content-Type'] = 'application/json';
+ }
+ console.log('Intercepted request', config);
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ },
+);
+
+export const request = axios.create({
+ baseURL: 'https://dev--mira-backend.netlify.app/.netlify/functions/api/v1',
+ headers: { Authorization: `Bearer ${token}` },
+ timeout: 4000,
+});
diff --git a/src/App/firebase/firebaseConfig.js b/src/App/firebase/firebaseConfig.js
new file mode 100644
index 0000000..9ad35cf
--- /dev/null
+++ b/src/App/firebase/firebaseConfig.js
@@ -0,0 +1,14 @@
+import { initializeApp } from 'firebase/app';
+import { getAuth } from 'firebase/auth';
+
+const firebaseConfig = {
+ apiKey: 'AIzaSyBzreTL2wHM_uGwTQO_DcQFleI2FBV4-CE',
+ authDomain: 'mira-v1-2b0a0.firebaseapp.com',
+ projectId: 'mira-v1-2b0a0',
+ storageBucket: 'mira-v1-2b0a0.appspot.com',
+ messagingSenderId: '887158081056',
+ appId: '1:887158081056:web:088bf484b65a27b0acde45',
+};
+
+const app = initializeApp(firebaseConfig);
+export const auth = getAuth(app);
diff --git a/src/App/hooks.ts b/src/App/hooks.ts
new file mode 100644
index 0000000..375dc31
--- /dev/null
+++ b/src/App/hooks.ts
@@ -0,0 +1,7 @@
+import { useDispatch, useSelector } from 'react-redux';
+import type { TypedUseSelectorHook } from 'react-redux';
+import type { RootState, AppDispatch } from './store';
+
+// Used throughout the app instead of plain `useDispatch` and `useSelector`
+export const useAppDispatch = () => useDispatch();
+export const useAppSelector: TypedUseSelectorHook = useSelector;
diff --git a/src/App/router.tsx b/src/App/router.tsx
index 13d8097..0f0bfb2 100644
--- a/src/App/router.tsx
+++ b/src/App/router.tsx
@@ -1,7 +1,9 @@
-import BaseLayout from 'components/layout/BaseLayout';
-import Login from 'components/Login';
-import Register from 'components/Register';
-import Home from 'pages/Home/Home';
+import BaseLayout from 'shared/components/layout/BaseLayout';
+import Login from 'features/auth/Login';
+import Register from 'features/auth/Register';
+import Home from 'features/home';
+import Status404 from 'features/home/Status404';
+// types
import type { RouteObject } from 'react-router';
const router: RouteObject[] = [
@@ -23,6 +25,10 @@ const router: RouteObject[] = [
},
],
},
+ {
+ path: '*',
+ element: ,
+ },
],
},
];
diff --git a/src/App/store.ts b/src/App/store.ts
new file mode 100644
index 0000000..71de037
--- /dev/null
+++ b/src/App/store.ts
@@ -0,0 +1,14 @@
+import { configureStore } from '@reduxjs/toolkit';
+import authReducer from 'features/auth/authSlice';
+
+const store = configureStore({
+ reducer: {
+ auth: authReducer,
+ },
+});
+
+export default store;
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType;
+// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
+export type AppDispatch = typeof store.dispatch;
diff --git a/src/components/Login.tsx b/src/components/Login.tsx
deleted file mode 100644
index 16aa430..0000000
--- a/src/components/Login.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import { useState } from 'react';
-import {
- Grid,
- Typography,
- Box,
- Link,
- InputAdornment,
- IconButton,
-} from '@mui/material';
-import Checkbox from '@mui/material/Checkbox';
-import FormControlLabel from '@mui/material/FormControlLabel';
-import ButtonWrapper from './common/ButtonWrapper';
-import TextFieldWrapper from './common/TextFieldWrapper';
-import Visibility from '@mui/icons-material/Visibility';
-import VisibilityOff from '@mui/icons-material/VisibilityOff';
-
-const Login = () => {
- const [showPassword, setShowPassword] = useState(false);
- const handleClickShowPassword = () => setShowPassword(!showPassword);
- const handleMouseDownPassword = () => setShowPassword(!showPassword);
-
- return (
- <>
-
- Login
-
-
-
-
-
-
-
- {showPassword ? : }
-
-
- ),
- }}
- >
-
-
- }
- label="Remember me"
- />
- }
- label="I Agree to all the Terms and Privacy Policy"
- />
-
-
- {
- alert('clicked');
- }}
- size="large"
- fullWidth
- sx={{
- margin: '10px 0px',
- padding: '10px',
- }}
- >
- Login
-
-
-
-
- Register
-
-
-
-
- Forgot password?
-
-
-
-
-
-
- >
- );
-};
-
-export default Login;
diff --git a/src/components/Register.tsx b/src/components/Register.tsx
deleted file mode 100644
index 37b59f1..0000000
--- a/src/components/Register.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import React, { useState } from 'react';
-import {
- FormControlLabel,
- Checkbox,
- Link,
- Box,
- Grid,
- Typography,
-} from '@mui/material';
-import TextFieldWrapper from 'components/common/TextFieldWrapper';
-import UploadImage from './common/UploadImage';
-import ButtonWrapper from './common/ButtonWrapper';
-
-const Register = () => {
- const [showPassword, setShowPassword] = useState(false);
-
- const handleSubmit = (event: React.FormEvent) => {
- event.preventDefault();
- const data = new FormData(event.currentTarget);
- console.log(data);
- };
-
- return (
-
- Create Account
-
-
-
- Profile Picture:
-
- (Use default or upload your own)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* */}
-
-
-
-
-
-
-
-
- }
- label="Show passwords"
- onChange={() => setShowPassword((prev) => !prev)}
- />
-
-
-
- {
- alert('clicked');
- }}
- size="large"
- fullWidth
- sx={{
- margin: '15px 0px',
- padding: '10px',
- }}
- >
- Create Account
-
-
-
-
-
- Already have an account? Sign in
-
-
-
-
- );
-};
-
-export default Register;
diff --git a/src/components/common/ButtonWrapper.tsx b/src/components/common/ButtonWrapper.tsx
deleted file mode 100644
index aea80d2..0000000
--- a/src/components/common/ButtonWrapper.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import { Button } from '@mui/material';
-
-type Props = any; // ExtendButtonBase;
-
-const ButtonWrapper: React.FC = (props) => {
- const { children, sx, ...buttonProps } = props;
- return (
-
- );
-};
-
-export default ButtonWrapper;
diff --git a/src/features/auth/Login.tsx b/src/features/auth/Login.tsx
new file mode 100644
index 0000000..8215620
--- /dev/null
+++ b/src/features/auth/Login.tsx
@@ -0,0 +1,171 @@
+import { useState } from 'react';
+import {
+ Grid,
+ Typography,
+ Box,
+ InputAdornment,
+ IconButton,
+ Checkbox,
+ FormControlLabel,
+} from '@mui/material';
+import { Visibility, VisibilityOff } from '@mui/icons-material';
+import ButtonWrapper from 'shared/components/ButtonWrapper';
+import TextFieldWrapper from 'shared/components/TextFieldWrapper';
+import LinkWrapper from 'shared/components/LinkWrapper';
+import GenericErrorModal from 'shared/components/Modal/GenericErrorModal';
+import ResetPassword from './ResetPassword';
+
+import { signInWithEmailAndPassword } from 'firebase/auth';
+import { auth } from 'app/firebase/firebaseConfig';
+
+interface ILoginData {
+ email: string;
+ password: string;
+ rememberMe: boolean;
+}
+
+const Login = () => {
+ const [showPassword, setShowPassword] = useState(false);
+ const [loginData, setLoginData] = useState({
+ email: '',
+ password: '',
+ rememberMe: false,
+ });
+ const [loading, setLoading] = useState(false);
+ const [openErrorModal, setOpenErrorModal] = useState(false);
+ const [resetPassword, setResetPassword] = useState(false);
+
+ const handleChange = (e: React.BaseSyntheticEvent) => {
+ const [value, name] = [
+ e.target.type === 'checkbox' ? e.target.checked : e.target.value,
+ e.target.name,
+ ];
+ setLoginData((prev) => ({ ...prev, [name]: value }));
+ };
+
+ const isLoginDisabled = () => {
+ if (!loginData.email || !loginData.password) return true;
+ return false;
+ };
+
+ const handleLoginSubmit = () => {
+ setLoading(true);
+ signInWithEmailAndPassword(auth, loginData.email, loginData.password)
+ .then((userCredential) => {
+ const user = userCredential.user;
+ console.log('Singed in user: ', user);
+ })
+ .catch((error) => {
+ const errorCode = error.code;
+ const errorMessage = error.message;
+ console.log('An error occured: ', errorCode, errorMessage);
+ setOpenErrorModal(true);
+ })
+ .finally(() => {
+ setLoading(false);
+ });
+ };
+
+ return (
+ <>
+
+ Login
+
+
+
+
+
+ {
+ if (e.key === 'Enter') {
+ handleLoginSubmit();
+ }
+ }}
+ type={showPassword ? 'text' : 'password'}
+ InputProps={{
+ endAdornment: (
+
+ setShowPassword(!showPassword)}
+ onMouseDown={() => setShowPassword(!showPassword)}
+ >
+ {showPassword ? : }
+
+
+ ),
+ }}
+ >
+
+
+
+ }
+ label="Remember me"
+ />
+
+
+ {
+
+ Login
+
+ }
+
+
+ Register
+
+
+ setResetPassword(true)}>
+ Forgot password?
+
+
+
+
+
+
+ {resetPassword && (
+ setResetPassword(false)} />
+ )}
+ setOpenErrorModal(false)}
+ >
+ >
+ );
+};
+
+export default Login;
diff --git a/src/features/auth/Register.tsx b/src/features/auth/Register.tsx
new file mode 100644
index 0000000..da81090
--- /dev/null
+++ b/src/features/auth/Register.tsx
@@ -0,0 +1,244 @@
+import React, { useState } from 'react';
+import {
+ FormControlLabel,
+ Checkbox,
+ Box,
+ Grid,
+ Typography,
+} from '@mui/material';
+import TextFieldWrapper from 'shared/components/TextFieldWrapper';
+import UploadImage from 'shared/components/UploadImage';
+import ButtonWrapper from 'shared/components/ButtonWrapper';
+import LinkWrapper from 'shared/components/LinkWrapper';
+import DatePickerWrapper from 'shared/components/DatePickerWrapper/DatePickerWrapper';
+import { IcustomEventObj } from 'shared/types';
+import GenericErrorModal from 'shared/components/Modal/GenericErrorModal';
+import { request } from 'app/axios';
+import { format } from 'date-fns';
+import { useSnackbar } from 'notistack';
+import { AxiosError } from 'axios';
+
+interface IRegisterData {
+ firstName: string;
+ lastName: string;
+ email: string;
+ password: string;
+ dob: Date;
+ confirmPassword: string;
+}
+
+const Register = () => {
+ const [errorMessage, setErrorMessage] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [openErrorModal, setOpenErrorModal] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
+ const [registerData, setRegisterData] = useState({
+ email: '',
+ password: '',
+ firstName: '',
+ lastName: '',
+ dob: new Date(),
+ confirmPassword: '',
+ });
+
+ const handleChange = (
+ e: React.BaseSyntheticEvent | IcustomEventObj,
+ ) => {
+ const [value, name] = [
+ e.target.type === 'checkbox' ? e.target.checked : e.target.value,
+ e.target.name,
+ ];
+ setRegisterData((prev) => ({ ...prev, [name]: value }));
+ setErrorMessage('');
+ };
+
+ const { enqueueSnackbar } = useSnackbar();
+
+ const handleSubmit = async () => {
+ const data = {
+ ...registerData,
+ dob: format(registerData.dob, 'yyyy-MM-dd'),
+ };
+ console.log(data);
+ if (!isFormValid()) return;
+
+ try {
+ setLoading(true);
+ const res = await request.post('/auth/signup', data);
+ console.log(res);
+ enqueueSnackbar('Signed in successfully! Please login to continue.', {
+ variant: 'success',
+ });
+ // TODO: redirect to /login page
+ } catch (error) {
+ console.log('/auth/signup', error);
+ // TODO: check all firebase errors and display
+ setErrorMessage((error as AxiosError).response?.data?.message);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const isFormValid = () => {
+ if (registerData.password !== registerData.confirmPassword) {
+ setErrorMessage('Passwords dont match!');
+ return false;
+ }
+ for (const key in registerData) {
+ if (!registerData[key]) {
+ setErrorMessage('Missing required fields!');
+ return false;
+ }
+ }
+ if (registerData.password.length < 6) {
+ setErrorMessage('Password should be atleast 6 characters');
+ return false;
+ }
+ setErrorMessage('');
+ return true;
+ };
+
+ return (
+ <>
+
+ Create Account
+
+
+
+ Profile Picture:
+
+ (Use default or upload your own)
+
+
+
+
+ handleChange({
+ target: {
+ name: 'avatar',
+ value: file,
+ },
+ })
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleChange({
+ target: {
+ name: 'dob',
+ value: val,
+ },
+ })
+ }
+ value={registerData.dob}
+ disableFuture
+ format="dd/MM/yyyy"
+ />
+
+
+
+
+
+
+
+
+ }
+ label="Show passwords"
+ onChange={() => setShowPassword((prev) => !prev)}
+ />
+
+
+ {errorMessage && (
+
+ {`Error: ${errorMessage}`}
+
+ )}
+
+
+ Create Account
+
+
+
+
+
+ Already have an account? Sign in
+
+
+
+
+ setOpenErrorModal(false)}
+ >
+ >
+ );
+};
+
+export default Register;
diff --git a/src/features/auth/ResetPassword.tsx b/src/features/auth/ResetPassword.tsx
new file mode 100644
index 0000000..80c5958
--- /dev/null
+++ b/src/features/auth/ResetPassword.tsx
@@ -0,0 +1,86 @@
+import React, { useState } from 'react';
+import DialogWrapper from 'shared/components/DialogWrapper/DialogWrapper';
+import TextFieldWrapper from 'shared/components/TextFieldWrapper';
+import { sleep } from 'shared/helpers/sleep';
+import CircularProgress from '@mui/material/CircularProgress';
+import { sendPasswordResetEmail } from 'firebase/auth';
+import { auth } from 'app/firebase/firebaseConfig';
+import { useSnackbar } from 'notistack';
+
+interface IResetPasswordProps {
+ onClose: () => void;
+}
+
+const ResetPassword: React.FunctionComponent = (props) => {
+ const { enqueueSnackbar } = useSnackbar();
+ const { onClose } = props;
+ const [dialogOpen, setDialogOpen] = useState(true);
+ const [email, setEmail] = useState('');
+ const [loading, setLoading] = useState(false);
+
+ const handleDialogClose = () => {
+ setDialogOpen(false);
+ onClose();
+ setLoading(false);
+ };
+
+ const handlePasswordReset = async () => {
+ setLoading(true);
+ await sleep(3000);
+ console.log(email);
+
+ sendPasswordResetEmail(auth, email)
+ .then(() => {
+ console.log('success');
+ enqueueSnackbar('Email sent successfully! - check it out!', {
+ variant: 'success',
+ });
+ })
+ .catch((error) => {
+ const errorCode = error.code;
+ const errorMessage = error.message;
+ enqueueSnackbar('Error Occured, please try again later!', {
+ variant: 'error',
+ });
+ console.log('An error has occured: ', errorCode, errorMessage);
+ })
+ .finally(() => {
+ handleDialogClose();
+ });
+ };
+
+ const renderContent = () => {
+ if (loading) {
+ return ;
+ } else {
+ return (
+ setEmail(e.target.value)}
+ required
+ autoFocus
+ >
+ );
+ }
+ };
+
+ return (
+
+ {renderContent()}
+
+ );
+};
+
+export default ResetPassword;
diff --git a/src/features/auth/authSlice.ts b/src/features/auth/authSlice.ts
new file mode 100644
index 0000000..411a666
--- /dev/null
+++ b/src/features/auth/authSlice.ts
@@ -0,0 +1,19 @@
+import { createSlice } from '@reduxjs/toolkit';
+import type { PayloadAction } from '@reduxjs/toolkit';
+
+const initialState: any = {};
+
+export const authSlice = createSlice({
+ name: 'user',
+ initialState,
+ reducers: {
+ saveUser: (state, action: PayloadAction) => {
+ state.value = action.payload;
+ },
+ },
+});
+
+// Action creators are generated for each case reducer function
+export const { saveUser } = authSlice.actions;
+
+export default authSlice.reducer;
diff --git a/src/pages/Home/Hero.tsx b/src/features/home/Hero.tsx
similarity index 100%
rename from src/pages/Home/Hero.tsx
rename to src/features/home/Hero.tsx
diff --git a/src/features/home/Status404.tsx b/src/features/home/Status404.tsx
new file mode 100644
index 0000000..488552a
--- /dev/null
+++ b/src/features/home/Status404.tsx
@@ -0,0 +1,45 @@
+import { Box, Typography, Container } from '@mui/material';
+
+import statusImg from 'app/assets/404.svg';
+
+import { styled } from '@mui/material/styles';
+import ButtonWrapper from 'shared/components/ButtonWrapper';
+
+const MainContent = styled(Box)(
+ ({ theme }) => `
+ height: 100%;
+ display: flex;
+ flex: 1;
+ overflow: auto;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+`,
+);
+
+function Status404() {
+ return (
+ <>
+
+
+
+
+
+ {`The page you were looking for doesn't exist.`}
+
+
+ {`Please click on the button below to start your journey with MIRA`}
+
+
+
+
+ Go to homepage
+
+
+
+
+ >
+ );
+}
+
+export default Status404;
diff --git a/src/pages/Home/Home.tsx b/src/features/home/index.tsx
similarity index 96%
rename from src/pages/Home/Home.tsx
rename to src/features/home/index.tsx
index 2a7ba67..d58c7ad 100644
--- a/src/pages/Home/Home.tsx
+++ b/src/features/home/index.tsx
@@ -1,7 +1,7 @@
import { Outlet, useLocation } from 'react-router-dom';
import { Box, Container, Grid, styled } from '@mui/material';
import Hero from './Hero';
-import HeroImage from 'App/assets/hero.png';
+import HeroImage from 'app/assets/hero.png';
const HomeWrapper = styled(Box)(
() => `
diff --git a/src/main.tsx b/src/main.tsx
index dc59c05..085606e 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,13 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.scss';
-import App from 'App/App';
+import App from 'app/App';
import { BrowserRouter } from 'react-router-dom';
+import { Provider } from 'react-redux';
+import store from 'app/store';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
-
-
+ //
+
+
-
- ,
+
+ ,
+ // ,
);
diff --git a/src/shared/components/ButtonWrapper/index.tsx b/src/shared/components/ButtonWrapper/index.tsx
new file mode 100644
index 0000000..f9e4fd3
--- /dev/null
+++ b/src/shared/components/ButtonWrapper/index.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Button } from '@mui/material';
+import LoadingButton from '@mui/lab/LoadingButton';
+
+type Props = any; // ExtendButtonBase;
+
+const style = {
+ margin: '15px 0px',
+ padding: '10px',
+};
+
+const ButtonWrapper: React.FC = (props) => {
+ const { children, loading, ...buttonProps } = props;
+ return loading ? (
+
+ Loading...
+
+ ) : (
+
+ );
+};
+
+export default ButtonWrapper;
diff --git a/src/shared/components/DatePickerWrapper/DatePickerWrapper.tsx b/src/shared/components/DatePickerWrapper/DatePickerWrapper.tsx
new file mode 100644
index 0000000..c2e3509
--- /dev/null
+++ b/src/shared/components/DatePickerWrapper/DatePickerWrapper.tsx
@@ -0,0 +1,40 @@
+import { DatePicker } from '@mui/x-date-pickers/DatePicker';
+import { InputLabel } from '@mui/material';
+import type { DatePickerProps } from '@mui/x-date-pickers/DatePicker';
+import type { SxProps, Theme } from '@mui/material';
+import type { PickerChangeHandler } from '@mui/x-date-pickers/internals/hooks/usePicker/usePickerValue';
+import type { DateValidationError } from '@mui/x-date-pickers';
+
+interface IDatePickerWrapperProps extends DatePickerProps {
+ label: string;
+ onChange: PickerChangeHandler;
+ value: Date | string;
+}
+
+const styles: SxProps = {
+ mt: 0,
+ mb: 0,
+ backgroundColor: 'secondary.main',
+ '&:hover': {
+ backgroundColor: 'secondary.light',
+ },
+ '& input:focus': {
+ backgroundColor: '#ffffff',
+ },
+};
+
+const DatePickerWrapper: React.FunctionComponent = ({
+ label,
+ value,
+ onChange,
+ ...props
+}) => {
+ return (
+ <>
+ {label && {label}}
+
+ >
+ );
+};
+
+export default DatePickerWrapper;
diff --git a/src/shared/components/DialogWrapper/DialogWrapper.tsx b/src/shared/components/DialogWrapper/DialogWrapper.tsx
new file mode 100644
index 0000000..96d8779
--- /dev/null
+++ b/src/shared/components/DialogWrapper/DialogWrapper.tsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+} from '@mui/material';
+import ButtonWrapper from '../ButtonWrapper';
+import type { DialogProps } from '@mui/material';
+
+interface IDialogWrapperProps extends DialogProps {
+ open: boolean;
+ handleClose: () => void;
+ handleOk: () => void;
+ title: string;
+ content?: string;
+ children?: React.ReactNode;
+ okText: string;
+ disableOk?: boolean;
+}
+
+const DialogWrapper: React.FunctionComponent = (props) => {
+ const {
+ open,
+ handleClose,
+ handleOk,
+ title,
+ content,
+ children,
+ okText = 'Ok',
+ disableOk = false,
+ ...rest
+ } = props;
+
+ return (
+
+ );
+};
+
+export default DialogWrapper;
diff --git a/src/components/common/Footer/Footer.tsx b/src/shared/components/Footer/index.tsx
similarity index 100%
rename from src/components/common/Footer/Footer.tsx
rename to src/shared/components/Footer/index.tsx
diff --git a/src/components/common/Header/Header.tsx b/src/shared/components/Header/index.tsx
similarity index 96%
rename from src/components/common/Header/Header.tsx
rename to src/shared/components/Header/index.tsx
index 21f6b68..f0eed8f 100644
--- a/src/components/common/Header/Header.tsx
+++ b/src/shared/components/Header/index.tsx
@@ -12,7 +12,7 @@ import {
MenuItem,
} from '@mui/material';
import MenuIcon from '@mui/icons-material/Menu';
-import Logo from 'App/assets/MIRA.png';
+import Logo from 'app/assets/MIRA.png';
const pages = [
{
@@ -48,8 +48,9 @@ function Header() {
>
-
-
+
+
+
> {
+ children: React.ReactNode;
+ href?: string;
+ onClick?: () => void;
+}
+
+const index: React.FC = ({ children, ...props }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default index;
diff --git a/src/shared/components/Modal/GenericErrorModal.tsx b/src/shared/components/Modal/GenericErrorModal.tsx
new file mode 100644
index 0000000..1b8c04f
--- /dev/null
+++ b/src/shared/components/Modal/GenericErrorModal.tsx
@@ -0,0 +1,101 @@
+import { Modal, Fade, Box, Typography, Backdrop } from '@mui/material';
+import * as React from 'react';
+import ButtonWrapper from '../ButtonWrapper';
+import ModalImage from 'app/assets/undraw_wandering_mind.svg';
+
+interface IGenericErrorModalProps {
+ open: boolean;
+ handleClose: () => void;
+ title?: string;
+ description?: string;
+}
+
+const style = {
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ transform: 'translate(-50%, -50%)',
+ width: 400,
+ bgcolor: 'background.paper',
+ borderRadius: '10px',
+ boxShadow: 24,
+ p: 4,
+ margin: {
+ sx: '10px',
+ },
+ '&:focus': {
+ border: 'none',
+ outline: 'none',
+ },
+};
+
+const GenericErrorModal: React.FunctionComponent = (
+ props,
+) => {
+ const {
+ open,
+ handleClose,
+ title = 'Something went wrong!',
+ description,
+ } = props;
+
+ return (
+
+
+
+
+ {title}
+
+
+
+
+
+ {description}
+
+
+ Close
+
+
+
+
+ );
+};
+
+export default GenericErrorModal;
diff --git a/src/components/common/TextFieldWrapper.tsx b/src/shared/components/TextFieldWrapper/index.tsx
similarity index 93%
rename from src/components/common/TextFieldWrapper.tsx
rename to src/shared/components/TextFieldWrapper/index.tsx
index 3bb9b5f..5658d01 100644
--- a/src/components/common/TextFieldWrapper.tsx
+++ b/src/shared/components/TextFieldWrapper/index.tsx
@@ -21,9 +21,8 @@ const TextFieldWrapper: React.FC = (props) => {
<>
{label && {label}}
`
@@ -43,20 +44,31 @@ const Input = styled('input')({
display: 'none',
});
-const UploadImage = () => {
+interface IProps {
+ onImageChange: (file: File) => void;
+}
+
+const UploadImage: React.FC = (props) => {
+ const [image, setImage] = useState(
+ 'https://i2.wp.com/thehealthyexec.com/wp-content/uploads/2015/11/reddit-logo.png',
+ );
+
+ const handleImageChange = (e: React.BaseSyntheticEvent) => {
+ console.log(e.target.files);
+ setImage(URL.createObjectURL(e.target.files[0]));
+ props.onImageChange(e.target.files[0]);
+ };
+
return (
-
+