Merge branch 'main' into home
This commit is contained in:
commit
4a2f14a388
476
package-lock.json
generated
476
package-lock.json
generated
@ -12,8 +12,13 @@
|
|||||||
"@emotion/styled": "^11.8.1",
|
"@emotion/styled": "^11.8.1",
|
||||||
"@mui/icons-material": "^5.4.2",
|
"@mui/icons-material": "^5.4.2",
|
||||||
"@mui/material": "^5.4.3",
|
"@mui/material": "^5.4.3",
|
||||||
|
"@reduxjs/toolkit": "^1.8.0",
|
||||||
|
"@types/react-big-calendar": "^0.36.2",
|
||||||
|
"moment": "^2.29.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-big-calendar": "^0.39.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-redux": "^7.2.6",
|
||||||
"react-router-dom": "^6.2.1"
|
"react-router-dom": "^6.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -2205,6 +2210,40 @@
|
|||||||
"url": "https://opencollective.com/popperjs"
|
"url": "https://opencollective.com/popperjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@reduxjs/toolkit": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-cdfHWfcvLyhBUDicoFwG1u32JqvwKDxLxDd7zSmSoFw/RhYLOygIRtmaMjPRUUHmVmmAGAvquLLsKKU/677kSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"immer": "^9.0.7",
|
||||||
|
"redux": "^4.1.2",
|
||||||
|
"redux-thunk": "^2.4.1",
|
||||||
|
"reselect": "^4.1.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.9.0 || ^17.0.0 || 18.0.0-beta",
|
||||||
|
"react-redux": "^7.2.1 || ^8.0.0-beta"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@restart/hooks": {
|
||||||
|
"version": "0.3.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.27.tgz",
|
||||||
|
"integrity": "sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==",
|
||||||
|
"dependencies": {
|
||||||
|
"dequal": "^2.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sindresorhus/is": {
|
"node_modules/@sindresorhus/is": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||||
@ -2560,6 +2599,15 @@
|
|||||||
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@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==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/html-minifier-terser": {
|
"node_modules/@types/html-minifier-terser": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
||||||
@ -2637,6 +2685,15 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-big-calendar": {
|
||||||
|
"version": "0.36.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-0.36.2.tgz",
|
||||||
|
"integrity": "sha512-grXQJgeHWXhgcipRB28NnUwIhD6aAKFs7IacGwy2+33hC8yAcR62nsW73aa25K3qxU8RxoLflKSCrsm4QCQpuQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-dom": {
|
"node_modules/@types/react-dom": {
|
||||||
"version": "17.0.11",
|
"version": "17.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
|
||||||
@ -2654,6 +2711,17 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-redux": {
|
||||||
|
"version": "7.1.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.23.tgz",
|
||||||
|
"integrity": "sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.0",
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-router": {
|
"node_modules/@types/react-router": {
|
||||||
"version": "5.1.18",
|
"version": "5.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
|
||||||
@ -2722,6 +2790,11 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/warning": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI="
|
||||||
|
},
|
||||||
"node_modules/@types/webpack": {
|
"node_modules/@types/webpack": {
|
||||||
"version": "5.28.0",
|
"version": "5.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.0.tgz",
|
||||||
@ -5153,6 +5226,11 @@
|
|||||||
"url": "https://github.com/imagemin/cwebp-bin?sponsor=1"
|
"url": "https://github.com/imagemin/cwebp-bin?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/date-arithmetic": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||||
@ -5498,6 +5576,14 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dequal": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/destroy": {
|
"node_modules/destroy": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
@ -7458,20 +7544,6 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/html-minifier-terser/node_modules/acorn": {
|
|
||||||
"version": "8.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"acorn": "bin/acorn"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/html-minifier-terser/node_modules/source-map": {
|
"node_modules/html-minifier-terser/node_modules/source-map": {
|
||||||
"version": "0.7.3",
|
"version": "0.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||||
@ -8163,6 +8235,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immer": {
|
||||||
|
"version": "9.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz",
|
||||||
|
"integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/immer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -8285,6 +8366,14 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ip": {
|
"node_modules/ip": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||||
@ -8962,8 +9051,12 @@
|
|||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
"dev": true
|
},
|
||||||
|
"node_modules/lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||||
},
|
},
|
||||||
"node_modules/lodash.debounce": {
|
"node_modules/lodash.debounce": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
@ -9073,6 +9166,11 @@
|
|||||||
"node": ">= 4.0.0"
|
"node": ">= 4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/memoize-one": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
|
},
|
||||||
"node_modules/memory-fs": {
|
"node_modules/memory-fs": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||||
@ -9216,6 +9314,14 @@
|
|||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.29.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
|
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mozjpeg": {
|
"node_modules/mozjpeg": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-7.1.1.tgz",
|
||||||
@ -10452,6 +10558,28 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-big-calendar": {
|
||||||
|
"version": "0.39.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-0.39.3.tgz",
|
||||||
|
"integrity": "sha512-RLymspfoBeYNBMvKnpMSpHtUAsJhv1Cbp1sE6aE7huQ92xT0mgnFDxUSoWc//C5J8WbYWLtlld521eisNJSjNw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.1.5",
|
||||||
|
"clsx": "^1.0.4",
|
||||||
|
"date-arithmetic": "^4.1.0",
|
||||||
|
"dom-helpers": "^5.1.0",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"lodash-es": "^4.17.11",
|
||||||
|
"memoize-one": "^5.1.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-overlays": "^4.1.1",
|
||||||
|
"uncontrollable": "^7.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.6.1 || ^17",
|
||||||
|
"react-dom": "^16.6.1 || ^17"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
@ -10470,6 +10598,59 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
|
"node_modules/react-overlays": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.1",
|
||||||
|
"@popperjs/core": "^2.5.3",
|
||||||
|
"@restart/hooks": "^0.3.25",
|
||||||
|
"@types/warning": "^3.0.0",
|
||||||
|
"dom-helpers": "^5.2.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"uncontrollable": "^7.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.3.0",
|
||||||
|
"react-dom": ">=16.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-redux": {
|
||||||
|
"version": "7.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||||
|
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.15.4",
|
||||||
|
"@types/react-redux": "^7.1.20",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^17.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.3 || ^17"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-redux/node_modules/react-is": {
|
||||||
|
"version": "17.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
||||||
@ -10548,6 +10729,22 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redux": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/redux-thunk": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"redux": "^4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -10698,6 +10895,11 @@
|
|||||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/reselect": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ=="
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.0",
|
"version": "1.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
||||||
@ -11808,20 +12010,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser-webpack-plugin/node_modules/acorn": {
|
|
||||||
"version": "8.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"acorn": "bin/acorn"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/terser-webpack-plugin/node_modules/commander": {
|
"node_modules/terser-webpack-plugin/node_modules/commander": {
|
||||||
"version": "2.20.3",
|
"version": "2.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
@ -12214,6 +12402,20 @@
|
|||||||
"through": "^2.3.8"
|
"through": "^2.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uncontrollable": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.6.3",
|
||||||
|
"@types/react": ">=16.9.11",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=15.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||||
@ -12361,6 +12563,14 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/warning": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/watchpack": {
|
"node_modules/watchpack": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
|
||||||
@ -14247,6 +14457,25 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
|
||||||
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
|
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
|
||||||
},
|
},
|
||||||
|
"@reduxjs/toolkit": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-cdfHWfcvLyhBUDicoFwG1u32JqvwKDxLxDd7zSmSoFw/RhYLOygIRtmaMjPRUUHmVmmAGAvquLLsKKU/677kSQ==",
|
||||||
|
"requires": {
|
||||||
|
"immer": "^9.0.7",
|
||||||
|
"redux": "^4.1.2",
|
||||||
|
"redux-thunk": "^2.4.1",
|
||||||
|
"reselect": "^4.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@restart/hooks": {
|
||||||
|
"version": "0.3.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.27.tgz",
|
||||||
|
"integrity": "sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==",
|
||||||
|
"requires": {
|
||||||
|
"dequal": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@sindresorhus/is": {
|
"@sindresorhus/is": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||||
@ -14498,6 +14727,15 @@
|
|||||||
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@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/html-minifier-terser": {
|
"@types/html-minifier-terser": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
|
||||||
@ -14575,6 +14813,15 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-big-calendar": {
|
||||||
|
"version": "0.36.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-0.36.2.tgz",
|
||||||
|
"integrity": "sha512-grXQJgeHWXhgcipRB28NnUwIhD6aAKFs7IacGwy2+33hC8yAcR62nsW73aa25K3qxU8RxoLflKSCrsm4QCQpuQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/prop-types": "*",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-dom": {
|
"@types/react-dom": {
|
||||||
"version": "17.0.11",
|
"version": "17.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
|
||||||
@ -14592,6 +14839,17 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-redux": {
|
||||||
|
"version": "7.1.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.23.tgz",
|
||||||
|
"integrity": "sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/hoist-non-react-statics": "^3.3.0",
|
||||||
|
"@types/react": "*",
|
||||||
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-router": {
|
"@types/react-router": {
|
||||||
"version": "5.1.18",
|
"version": "5.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz",
|
||||||
@ -14660,6 +14918,11 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/warning": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI="
|
||||||
|
},
|
||||||
"@types/webpack": {
|
"@types/webpack": {
|
||||||
"version": "5.28.0",
|
"version": "5.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.0.tgz",
|
||||||
@ -16529,6 +16792,11 @@
|
|||||||
"bin-wrapper": "^4.0.1"
|
"bin-wrapper": "^4.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"date-arithmetic": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||||
@ -16797,6 +17065,11 @@
|
|||||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dequal": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug=="
|
||||||
|
},
|
||||||
"destroy": {
|
"destroy": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
@ -18309,14 +18582,6 @@
|
|||||||
"terser": "^5.10.0"
|
"terser": "^5.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": {
|
|
||||||
"version": "8.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.7.3",
|
"version": "0.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||||
@ -18827,6 +19092,11 @@
|
|||||||
"is-cwebp-readable": "^3.0.0"
|
"is-cwebp-readable": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"immer": {
|
||||||
|
"version": "9.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz",
|
||||||
|
"integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA=="
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -18916,6 +19186,14 @@
|
|||||||
"p-is-promise": "^1.1.0"
|
"p-is-promise": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ip": {
|
"ip": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||||
@ -19401,8 +19679,12 @@
|
|||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
"dev": true
|
},
|
||||||
|
"lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||||
},
|
},
|
||||||
"lodash.debounce": {
|
"lodash.debounce": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
@ -19491,6 +19773,11 @@
|
|||||||
"fs-monkey": "1.0.3"
|
"fs-monkey": "1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"memoize-one": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
|
},
|
||||||
"memory-fs": {
|
"memory-fs": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||||
@ -19598,6 +19885,11 @@
|
|||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.29.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
|
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||||
|
},
|
||||||
"mozjpeg": {
|
"mozjpeg": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-7.1.1.tgz",
|
||||||
@ -20506,6 +20798,24 @@
|
|||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-big-calendar": {
|
||||||
|
"version": "0.39.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-0.39.3.tgz",
|
||||||
|
"integrity": "sha512-RLymspfoBeYNBMvKnpMSpHtUAsJhv1Cbp1sE6aE7huQ92xT0mgnFDxUSoWc//C5J8WbYWLtlld521eisNJSjNw==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.5",
|
||||||
|
"clsx": "^1.0.4",
|
||||||
|
"date-arithmetic": "^4.1.0",
|
||||||
|
"dom-helpers": "^5.1.0",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"lodash-es": "^4.17.11",
|
||||||
|
"memoize-one": "^5.1.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-overlays": "^4.1.1",
|
||||||
|
"uncontrollable": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||||
@ -20521,6 +20831,46 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
|
"react-overlays": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.1",
|
||||||
|
"@popperjs/core": "^2.5.3",
|
||||||
|
"@restart/hooks": "^0.3.25",
|
||||||
|
"@types/warning": "^3.0.0",
|
||||||
|
"dom-helpers": "^5.2.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"uncontrollable": "^7.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"version": "7.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz",
|
||||||
|
"integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.15.4",
|
||||||
|
"@types/react-redux": "^7.1.20",
|
||||||
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^17.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react-is": {
|
||||||
|
"version": "17.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-router": {
|
"react-router": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
||||||
@ -20582,6 +20932,20 @@
|
|||||||
"resolve": "^1.9.0"
|
"resolve": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redux": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.9.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redux-thunk": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -20701,6 +21065,11 @@
|
|||||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"reselect": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ=="
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.22.0",
|
"version": "1.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
|
||||||
@ -21583,14 +21952,6 @@
|
|||||||
"terser": "^5.7.2"
|
"terser": "^5.7.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": {
|
|
||||||
"version": "8.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"commander": {
|
"commander": {
|
||||||
"version": "2.20.3",
|
"version": "2.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
@ -21872,6 +22233,17 @@
|
|||||||
"through": "^2.3.8"
|
"through": "^2.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"uncontrollable": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.6.3",
|
||||||
|
"@types/react": ">=16.9.11",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"unicode-canonical-property-names-ecmascript": {
|
"unicode-canonical-property-names-ecmascript": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
|
||||||
@ -21986,6 +22358,14 @@
|
|||||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"warning": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz",
|
||||||
|
|||||||
@ -12,8 +12,13 @@
|
|||||||
"@emotion/styled": "^11.8.1",
|
"@emotion/styled": "^11.8.1",
|
||||||
"@mui/icons-material": "^5.4.2",
|
"@mui/icons-material": "^5.4.2",
|
||||||
"@mui/material": "^5.4.3",
|
"@mui/material": "^5.4.3",
|
||||||
|
"@reduxjs/toolkit": "^1.8.0",
|
||||||
|
"@types/react-big-calendar": "^0.36.2",
|
||||||
|
"moment": "^2.29.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-big-calendar": "^0.39.3",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-redux": "^7.2.6",
|
||||||
"react-router-dom": "^6.2.1"
|
"react-router-dom": "^6.2.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
15
src/App.tsx
15
src/App.tsx
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
|
||||||
import Login from "./components/login/Login";
|
import Login from "./components/login/Login";
|
||||||
import Home from "./components/home/Home";
|
import Home from "./components/home/Home";
|
||||||
import Contacts from "./components/contacts/Contacts";
|
import Contacts from "./components/contacts/Contacts";
|
||||||
import Calendar from "./components/calendar/Calendar";
|
import CalendarPage from "./components/calendar/CalendarPage";
|
||||||
import { ThemeProvider } from "@emotion/react";
|
import { ThemeProvider } from "@emotion/react";
|
||||||
import ProtectedRoute from "./ProtectedRoute";
|
import ProtectedRoute from "./ProtectedRoute";
|
||||||
import MeetingDetails from "./components/meeting-details/MeetingDetails";
|
import MeetingDetails from "./components/meeting-details/MeetingDetails";
|
||||||
@ -15,8 +15,6 @@ import Theme from "./Theme";
|
|||||||
import "./style/App.css";
|
import "./style/App.css";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [meetingInfoOpen, setMeetingInfoOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={Theme}>
|
<ThemeProvider theme={Theme}>
|
||||||
<Router>
|
<Router>
|
||||||
@ -24,15 +22,12 @@ const App: React.FC = () => {
|
|||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
<Route element={<ProtectedRoute />}>
|
<Route element={<ProtectedRoute />}>
|
||||||
<Route path="/" element={<Home />} />
|
<Route path="/" element={<Home />} />
|
||||||
<Route
|
<Route path="/contacts" element={<Contacts />} />
|
||||||
path="/contacts"
|
<Route path="/calendar" element={<CalendarPage />} />
|
||||||
element={<Contacts setMeetingInfoOpen={setMeetingInfoOpen} />}
|
|
||||||
/>
|
|
||||||
<Route path="/calendar" element={<Calendar />} />
|
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
<MeetingDetails open={meetingInfoOpen} setOpen={setMeetingInfoOpen} />
|
<MeetingDetails />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
import {useLocation, Outlet, Navigate, Routes, Route} from "react-router-dom";
|
import {useLocation, Outlet, Navigate} from "react-router-dom";
|
||||||
import useAuth from "./hooks/useAuth";
|
import useAuth from "./hooks/useAuth";
|
||||||
import Navbar from "./components/navbar/Navbar";
|
import Navbar from "./components/navbar/Navbar";
|
||||||
import Sidebar from "./components/sidebar/Sidebar";
|
import Sidebar from "./components/sidebar/Sidebar";
|
||||||
import React, {useState} from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
MeetingStatus,
|
MeetingStatus,
|
||||||
SidebarUserObj,
|
SidebarUserObj,
|
||||||
} from "./components/sidebar/SidebarUser";
|
} from "./components/sidebar/SidebarUser";
|
||||||
import {Box} from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
const ProtectedRoute = () => {
|
const ProtectedRoute = () => {
|
||||||
const { auth }: any = useAuth();
|
const auth= useAuth();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const [meetingInfoOpen, setMeetingInfoOpen] = useState(false);
|
|
||||||
/* Temporary data */
|
/* Temporary data */
|
||||||
const [sidebarUsers] = useState<SidebarUserObj[]>([
|
const [sidebarUsers] = useState<SidebarUserObj[]>([
|
||||||
{ id: 0, name: "Jincheng L.", meetingStatus: MeetingStatus.ONLINE },
|
{ id: 0, name: "Jincheng L.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
@ -38,21 +37,20 @@ const ProtectedRoute = () => {
|
|||||||
{ id: 19, name: "Bob Q.", meetingStatus: MeetingStatus.ONLINE },
|
{ id: 19, name: "Bob Q.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
{ id: 20, name: "Bob R.", meetingStatus: MeetingStatus.ONLINE },
|
{ id: 20, name: "Bob R.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
]);
|
]);
|
||||||
return (
|
return auth?.isLoggedIn ? (
|
||||||
auth?.isLoggedIn
|
<>
|
||||||
?
|
<Navbar />
|
||||||
<>
|
<Box id="drawer-container" sx={{ display: "flex", height: "100%" }}>
|
||||||
<Navbar />
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
<Box id="drawer-container" sx={{ display: "flex", height: "100%" }}>
|
<Outlet />
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
|
||||||
<Outlet />
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Sidebar users={sidebarUsers} />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
<Box>
|
||||||
: <Navigate to="/login" state={{ from: location }} replace />
|
<Sidebar users={sidebarUsers} />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Navigate to="/login" state={{ from: location }} replace />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
86
src/api-bodies/MockData.tsx
Normal file
86
src/api-bodies/MockData.tsx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
const people = [
|
||||||
|
{
|
||||||
|
uuid: "0",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Taehee Choi",
|
||||||
|
role: "Front-end Dev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "1",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Arthur Marques",
|
||||||
|
role: "Team Lead",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "2",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Mathew Balsdon",
|
||||||
|
role: "Front-end Dev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "3",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Benson Lin",
|
||||||
|
role: "Back-end Dev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "4",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Jincheng Lu",
|
||||||
|
role: "Front-end Dev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "5",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Esteban Margaron",
|
||||||
|
role: "Back-end Dev",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "6",
|
||||||
|
emailAddress: "cth0604@gmail.com",
|
||||||
|
name: "Leanna Resurreccion",
|
||||||
|
role: "Back-end Dev",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const meetings = [
|
||||||
|
{
|
||||||
|
meetingId: "0",
|
||||||
|
liveParticipantIds: [],
|
||||||
|
registrantIds: ["0", "1", "2", "3", "4", "5", "6"],
|
||||||
|
start: "2022-03-13T17:00:00",
|
||||||
|
duration: 15,
|
||||||
|
timezone: "",
|
||||||
|
joinUrl: "",
|
||||||
|
topic: "Daily Scrum Meeting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
meetingId: "1",
|
||||||
|
liveParticipantIds: [],
|
||||||
|
registrantIds: ["0", "2", "4"],
|
||||||
|
start: "2022-03-13T17:30:00",
|
||||||
|
duration: 30,
|
||||||
|
timezone: "",
|
||||||
|
joinUrl: "",
|
||||||
|
topic: "Front-end Meeting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
meetingId: "2",
|
||||||
|
liveParticipantIds: [],
|
||||||
|
registrantIds: ["3", "5", "6"],
|
||||||
|
start: "2022-03-13T17:30:00",
|
||||||
|
duration: 30,
|
||||||
|
timezone: "",
|
||||||
|
joinUrl: "",
|
||||||
|
topic: "Back-end Meeting",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const team = {
|
||||||
|
user: "0",
|
||||||
|
manager: "1",
|
||||||
|
sameManager: ["2", "3", "4", "5", "6"],
|
||||||
|
directReports: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export { people, meetings, team };
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const Calendar: React.FC = () => {
|
|
||||||
return <span>Calendar</span>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Calendar;
|
|
||||||
14
src/components/calendar/CalendarPage.tsx
Normal file
14
src/components/calendar/CalendarPage.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Toolbar } from "@mui/material";
|
||||||
|
import UserCalendar from "./UserCalendar";
|
||||||
|
|
||||||
|
const CalendarPage: React.FC = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Toolbar />
|
||||||
|
<UserCalendar />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CalendarPage;
|
||||||
185
src/components/calendar/Events.tsx
Normal file
185
src/components/calendar/Events.tsx
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
Test data from
|
||||||
|
https://github.com/jquense/react-big-calendar/blob/master/examples/events.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "All Day Event very long title",
|
||||||
|
allDay: true,
|
||||||
|
start: new Date(2022, 2, 0),
|
||||||
|
end: new Date(2022, 2, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Long Event",
|
||||||
|
start: new Date(2022, 2, 7),
|
||||||
|
end: new Date(2022, 2, 10),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "DTS STARTS",
|
||||||
|
start: new Date(2022, 1, 13, 0, 0, 0),
|
||||||
|
end: new Date(2022, 1, 20, 0, 0, 0),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "DTS ENDS",
|
||||||
|
start: new Date(2022, 9, 6, 0, 0, 0),
|
||||||
|
end: new Date(2022, 9, 13, 0, 0, 0),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "Some Event",
|
||||||
|
start: new Date(2022, 2, 9, 0, 0, 0),
|
||||||
|
end: new Date(2022, 2, 10, 0, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: "Conference",
|
||||||
|
start: new Date(2022, 2, 11),
|
||||||
|
end: new Date(2022, 2, 13),
|
||||||
|
desc: "Big conference for important people",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: "Meeting",
|
||||||
|
start: new Date(2022, 2, 12, 10, 30, 0, 0),
|
||||||
|
end: new Date(2022, 2, 12, 12, 30, 0, 0),
|
||||||
|
desc: "Pre-meeting meeting, to prepare for the meeting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: "Lunch",
|
||||||
|
start: new Date(2022, 2, 12, 12, 0, 0, 0),
|
||||||
|
end: new Date(2022, 2, 12, 13, 0, 0, 0),
|
||||||
|
desc: "Power lunch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
title: "Meeting",
|
||||||
|
start: new Date(2022, 2, 12, 14, 0, 0, 0),
|
||||||
|
end: new Date(2022, 2, 12, 15, 0, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
title: "Happy Hour",
|
||||||
|
start: new Date(2022, 2, 12, 17, 0, 0, 0),
|
||||||
|
end: new Date(2022, 2, 12, 17, 30, 0, 0),
|
||||||
|
desc: "Most important meal of the day",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
title: "Dinner",
|
||||||
|
start: new Date(2022, 2, 12, 20, 0, 0, 0),
|
||||||
|
end: new Date(2022, 2, 12, 21, 0, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
title: "Planning Meeting with Paige",
|
||||||
|
start: new Date(2022, 2, 13, 8, 0, 0),
|
||||||
|
end: new Date(2022, 2, 13, 10, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11.1,
|
||||||
|
title: "Inconvenient multi-day Conference Call",
|
||||||
|
start: new Date(2022, 2, 13, 9, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 1, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11.2,
|
||||||
|
title: "Project Kickoff - Lou's Shoes",
|
||||||
|
start: new Date(2022, 2, 13, 11, 30, 0),
|
||||||
|
end: new Date(2022, 2, 13, 14, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11.3,
|
||||||
|
title: "Quote Follow-up - Tea by Tina",
|
||||||
|
start: new Date(2022, 2, 13, 15, 30, 0),
|
||||||
|
end: new Date(2022, 2, 13, 16, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
title: "Late Night Event",
|
||||||
|
start: new Date(2022, 2, 17, 19, 30, 0),
|
||||||
|
end: new Date(2022, 2, 18, 2, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12.5,
|
||||||
|
title: "Late Same Night Event",
|
||||||
|
start: new Date(2022, 2, 17, 19, 30, 0),
|
||||||
|
end: new Date(2022, 2, 17, 23, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
title: "Multi-day Event",
|
||||||
|
start: new Date(2022, 2, 20, 19, 30, 0),
|
||||||
|
end: new Date(2022, 2, 22, 2, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 14,
|
||||||
|
title: "Today",
|
||||||
|
start: new Date(new Date().setHours(new Date().getHours() - 3)),
|
||||||
|
end: new Date(new Date().setHours(new Date().getHours() + 3)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 15,
|
||||||
|
title: "Point in Time Event",
|
||||||
|
start: now,
|
||||||
|
end: now,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 16,
|
||||||
|
title: "Video Record",
|
||||||
|
start: new Date(2022, 2, 14, 15, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 19, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 17,
|
||||||
|
title: "Dutch Song Producing",
|
||||||
|
start: new Date(2022, 2, 14, 16, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 20, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 18,
|
||||||
|
title: "Itaewon Halloween Meeting",
|
||||||
|
start: new Date(2022, 2, 14, 16, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 17, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 19,
|
||||||
|
title: "Online Coding Test",
|
||||||
|
start: new Date(2022, 2, 14, 17, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 20, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 20,
|
||||||
|
title: "An overlapped Event",
|
||||||
|
start: new Date(2022, 2, 14, 17, 0, 0),
|
||||||
|
end: new Date(2022, 2, 14, 18, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 21,
|
||||||
|
title: "Phone Interview",
|
||||||
|
start: new Date(2022, 2, 14, 17, 0, 0),
|
||||||
|
end: new Date(2022, 2, 14, 18, 30, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 22,
|
||||||
|
title: "Cooking Class",
|
||||||
|
start: new Date(2022, 2, 14, 17, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 19, 0, 0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 23,
|
||||||
|
title: "Go to the gym",
|
||||||
|
start: new Date(2022, 2, 14, 18, 30, 0),
|
||||||
|
end: new Date(2022, 2, 14, 20, 0, 0),
|
||||||
|
},
|
||||||
|
];
|
||||||
23
src/components/calendar/UserCalendar.tsx
Normal file
23
src/components/calendar/UserCalendar.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Calendar, momentLocalizer } from "react-big-calendar";
|
||||||
|
import moment from "moment";
|
||||||
|
import testEvents from "./Events";
|
||||||
|
|
||||||
|
import "react-big-calendar/lib/css/react-big-calendar.css";
|
||||||
|
|
||||||
|
const localizer = momentLocalizer(moment);
|
||||||
|
|
||||||
|
const UserCalendar: React.FC = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Calendar
|
||||||
|
events={testEvents}
|
||||||
|
views={["month", "week", "day"]}
|
||||||
|
step={60}
|
||||||
|
showMultiDayTimes
|
||||||
|
localizer={localizer}
|
||||||
|
style={{ height: "80%" }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserCalendar;
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import Status from "./Status";
|
|
||||||
|
|
||||||
interface ContactInfo {
|
|
||||||
name: string;
|
|
||||||
status: Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ContactInfo;
|
|
||||||
@ -2,25 +2,19 @@ import { Box } from "@mui/material";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Body from "./contacts-components/Body";
|
import Body from "./contacts-components/Body";
|
||||||
|
|
||||||
import ContactInfo from "./ContactInfo";
|
|
||||||
import Sidebar from "./contacts-components/Sidebar";
|
import Sidebar from "./contacts-components/Sidebar";
|
||||||
|
import UserLite from "../../api-bodies/UserLite";
|
||||||
|
|
||||||
interface Props {
|
const Contacts: React.FC = () => {
|
||||||
setMeetingInfoOpen: (open: boolean) => void;
|
const [contactSelected, setContactSelected] = React.useState<UserLite | null>(
|
||||||
}
|
null
|
||||||
|
);
|
||||||
const Contacts: React.FC<Props> = (props) => {
|
|
||||||
const [contactSelected, setContactSelected] =
|
|
||||||
React.useState<ContactInfo | null>(null);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "flex", height: "100%" }}>
|
<Box sx={{ display: "flex", height: "100%" }}>
|
||||||
<Sidebar setContactSelected={setContactSelected} />
|
<Sidebar setContactSelected={setContactSelected} />
|
||||||
{contactSelected !== null ? (
|
{contactSelected !== null ? (
|
||||||
<Body
|
<Body contactSelected={contactSelected} />
|
||||||
contactSelected={contactSelected}
|
|
||||||
setMeetingInfoOpen={props.setMeetingInfoOpen}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
|
||||||
import Status from "./Status";
|
import Status from "./Status";
|
||||||
|
|
||||||
const returnStatusColor = (
|
const returnStatusColor = (
|
||||||
@ -15,4 +16,10 @@ const returnStatusColor = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { returnStatusColor };
|
const getMeetingDuration = (meeting: DetailedMeeting) => {
|
||||||
|
const startDate = new Date(meeting.start);
|
||||||
|
const endDate = new Date(startDate.getTime() + meeting.duration * 60000);
|
||||||
|
return `${startDate.toTimeString()} - ${endDate.toTimeString()}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { returnStatusColor, getMeetingDuration };
|
||||||
|
|||||||
@ -2,11 +2,10 @@ import { Box, Toolbar } from "@mui/material";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import UpperBody from "./body-components/UpperBody";
|
import UpperBody from "./body-components/UpperBody";
|
||||||
import LowerBody from "./body-components/LowerBody";
|
import LowerBody from "./body-components/LowerBody";
|
||||||
import ContactInfo from "../ContactInfo";
|
import UserLite from "../../../api-bodies/UserLite";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contactSelected: ContactInfo;
|
contactSelected: UserLite;
|
||||||
setMeetingInfoOpen: (open: boolean) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Body: React.FC<Props> = (props) => {
|
const Body: React.FC<Props> = (props) => {
|
||||||
@ -21,10 +20,7 @@ const Body: React.FC<Props> = (props) => {
|
|||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<UpperBody contactInfo={props.contactSelected} />
|
<UpperBody contactInfo={props.contactSelected} />
|
||||||
<LowerBody
|
<LowerBody contactInfo={props.contactSelected} />
|
||||||
contactInfo={props.contactSelected}
|
|
||||||
setMeetingInfoOpen={props.setMeetingInfoOpen}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,19 +9,17 @@ import {
|
|||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||||
import ContactInfo from "../ContactInfo";
|
|
||||||
import Status from "../Status";
|
|
||||||
import ContactItem from "./sidebar-components/ContactItem";
|
import ContactItem from "./sidebar-components/ContactItem";
|
||||||
|
import { useAppSelector } from "../../../redux/hooks";
|
||||||
const contacts: ContactInfo[] = [
|
import {
|
||||||
{ name: "Taehee ...", status: Status.Online },
|
selectFavoritesJSON,
|
||||||
{ name: "Jincheng ...", status: Status.Offline },
|
selectTeamJSON,
|
||||||
{ name: "Mathew ...", status: Status.InMeeting },
|
} from "../../../redux/slices/peopleSlice";
|
||||||
{ name: "Esteban ...", status: Status.Away },
|
import { selectFavorites } from "../../../redux/slices/favoritesSlice";
|
||||||
];
|
import UserLite from "../../../api-bodies/UserLite";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setContactSelected: (contactInfo: ContactInfo) => void;
|
setContactSelected: (contactInfo: UserLite) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sidebarWidth = 240;
|
const sidebarWidth = 240;
|
||||||
@ -30,6 +28,12 @@ const Sidebar: React.FC<Props> = (props) => {
|
|||||||
const [favoritesOpen, setFavoritesOpen] = React.useState<boolean>(true);
|
const [favoritesOpen, setFavoritesOpen] = React.useState<boolean>(true);
|
||||||
const [teamOpen, setTeamOpen] = React.useState<boolean>(false);
|
const [teamOpen, setTeamOpen] = React.useState<boolean>(false);
|
||||||
|
|
||||||
|
const favorites = useAppSelector(selectFavorites);
|
||||||
|
const favoritesJSON = useAppSelector((state) =>
|
||||||
|
selectFavoritesJSON(state, favorites)
|
||||||
|
);
|
||||||
|
const teamJSON = useAppSelector(selectTeamJSON);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
variant="permanent"
|
variant="permanent"
|
||||||
@ -49,13 +53,16 @@ const Sidebar: React.FC<Props> = (props) => {
|
|||||||
<ListItemButton onClick={() => setFavoritesOpen(!favoritesOpen)}>
|
<ListItemButton onClick={() => setFavoritesOpen(!favoritesOpen)}>
|
||||||
{favoritesOpen ? <ExpandLess /> : <ExpandMore />}
|
{favoritesOpen ? <ExpandLess /> : <ExpandMore />}
|
||||||
<ListItemText primary="Favorites" sx={{ textAlign: "center" }} />
|
<ListItemText primary="Favorites" sx={{ textAlign: "center" }} />
|
||||||
<ListItemText primary="10" sx={{ textAlign: "right" }} />
|
<ListItemText
|
||||||
|
primary={favoritesJSON.length}
|
||||||
|
sx={{ textAlign: "right" }}
|
||||||
|
/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
<Collapse in={favoritesOpen} timeout="auto" unmountOnExit>
|
<Collapse in={favoritesOpen} timeout="auto" unmountOnExit>
|
||||||
<List disablePadding>
|
<List disablePadding>
|
||||||
{contacts.map((contact, i) => (
|
{favoritesJSON.map((favorite, i) => (
|
||||||
<ContactItem
|
<ContactItem
|
||||||
contactInfo={contact}
|
contactInfo={favorite}
|
||||||
key={i}
|
key={i}
|
||||||
setContactSelected={props.setContactSelected}
|
setContactSelected={props.setContactSelected}
|
||||||
/>
|
/>
|
||||||
@ -65,13 +72,13 @@ const Sidebar: React.FC<Props> = (props) => {
|
|||||||
<ListItemButton onClick={() => setTeamOpen(!teamOpen)}>
|
<ListItemButton onClick={() => setTeamOpen(!teamOpen)}>
|
||||||
{teamOpen ? <ExpandLess /> : <ExpandMore />}
|
{teamOpen ? <ExpandLess /> : <ExpandMore />}
|
||||||
<ListItemText primary="Team" sx={{ textAlign: "center" }} />
|
<ListItemText primary="Team" sx={{ textAlign: "center" }} />
|
||||||
<ListItemText primary="10" sx={{ textAlign: "right" }} />
|
<ListItemText primary={teamJSON.length} sx={{ textAlign: "right" }} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
<Collapse in={teamOpen} timeout="auto" unmountOnExit>
|
<Collapse in={teamOpen} timeout="auto" unmountOnExit>
|
||||||
<List disablePadding>
|
<List disablePadding>
|
||||||
{contacts.map((contact, i) => (
|
{teamJSON.map((member, i) => (
|
||||||
<ContactItem
|
<ContactItem
|
||||||
contactInfo={contact}
|
contactInfo={member}
|
||||||
key={i}
|
key={i}
|
||||||
setContactSelected={props.setContactSelected}
|
setContactSelected={props.setContactSelected}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
import { Box, Button, List, Typography } from "@mui/material";
|
import { Box, Button, List, Typography } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ContactInfo from "../../ContactInfo";
|
import UserLite from "../../../../api-bodies/UserLite";
|
||||||
|
import { useAppSelector, useAppDispatch } from "../../../../redux/hooks";
|
||||||
const meetings: { name: string; duration: string }[] = [
|
import { open } from "../../../../redux/slices/meetingDetailsOpenSlice";
|
||||||
{ name: "Kanban Meeting", duration: "10:45 am - 11:45 am" },
|
import { selectUserUpcomingMeetings } from "../../../../redux/slices/meetingsSlice";
|
||||||
{ name: "Design Meeting", duration: "10:45 am - 11:45 am" },
|
import { getMeetingDuration } from "../../Utils";
|
||||||
{ name: "Customer Meeting", duration: "10:45 am - 11:45 am" },
|
|
||||||
{ name: "Some kind of Meeting", duration: "10:45 am - 11:45 am" },
|
|
||||||
{ name: "Some kind of Meeting", duration: "10:45 am - 11:45 am" },
|
|
||||||
];
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contactInfo: ContactInfo;
|
contactInfo: UserLite;
|
||||||
setMeetingInfoOpen: (open: boolean) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LowerBody: React.FC<Props> = (props) => {
|
const LowerBody: React.FC<Props> = (props) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const meetings = useAppSelector((state) =>
|
||||||
|
selectUserUpcomingMeetings(state, props.contactInfo.uuid)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -47,11 +48,13 @@ const LowerBody: React.FC<Props> = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="text"
|
variant="text"
|
||||||
color="info"
|
color="info"
|
||||||
onClick={() => props.setMeetingInfoOpen(true)}
|
onClick={() => dispatch(open(meeting))}
|
||||||
>
|
>
|
||||||
{meeting.name}
|
{meeting.topic}
|
||||||
</Button>
|
</Button>
|
||||||
<Typography sx={{ pt: 1.5 }}>{meeting.duration}</Typography>
|
<Typography sx={{ pt: 1.5 }}>
|
||||||
|
{getMeetingDuration(meeting)}
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
|||||||
@ -3,11 +3,12 @@ import React from "react";
|
|||||||
import PhoneIcon from "@mui/icons-material/Phone";
|
import PhoneIcon from "@mui/icons-material/Phone";
|
||||||
import VideocamIcon from "@mui/icons-material/Videocam";
|
import VideocamIcon from "@mui/icons-material/Videocam";
|
||||||
import GroupsIcon from "@mui/icons-material/Groups";
|
import GroupsIcon from "@mui/icons-material/Groups";
|
||||||
import ContactInfo from "../../ContactInfo";
|
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
|
import Status from "../../Status";
|
||||||
|
import UserLite from "../../../../api-bodies/UserLite";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contactInfo: ContactInfo;
|
contactInfo: UserLite;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UpperBody: React.FC<Props> = (props) => {
|
const UpperBody: React.FC<Props> = (props) => {
|
||||||
@ -63,9 +64,7 @@ const UpperBody: React.FC<Props> = (props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||||
<Typography sx={{ textAlign: "right" }}>
|
<Typography sx={{ textAlign: "right" }}>{Status.Online}</Typography>
|
||||||
{props.contactInfo.status}
|
|
||||||
</Typography>
|
|
||||||
<Typography>MeetingName-1372</Typography>
|
<Typography>MeetingName-1372</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -2,12 +2,13 @@ import { ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
||||||
import CircleIcon from "@mui/icons-material/Circle";
|
import CircleIcon from "@mui/icons-material/Circle";
|
||||||
import ContactInfo from "../../ContactInfo";
|
|
||||||
import { returnStatusColor } from "../../Utils";
|
import { returnStatusColor } from "../../Utils";
|
||||||
|
import UserLite from "../../../../api-bodies/UserLite";
|
||||||
|
import Status from "../../Status";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
contactInfo: ContactInfo;
|
contactInfo: UserLite;
|
||||||
setContactSelected: (contactInfo: ContactInfo) => void;
|
setContactSelected: (contactInfo: UserLite) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContactItem: React.FC<Props> = (props) => {
|
const ContactItem: React.FC<Props> = (props) => {
|
||||||
@ -22,10 +23,10 @@ const ContactItem: React.FC<Props> = (props) => {
|
|||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={props.contactInfo.name}
|
primary={props.contactInfo.name}
|
||||||
secondary={props.contactInfo.status}
|
secondary={Status.Online}
|
||||||
sx={{ flexGrow: 1 }}
|
sx={{ flexGrow: 1 }}
|
||||||
/>
|
/>
|
||||||
<CircleIcon color={returnStatusColor(props.contactInfo.status)} />
|
<CircleIcon color={returnStatusColor(Status.Online)} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
44
src/components/home/CallFavouritesDialog.tsx
Normal file
44
src/components/home/CallFavouritesDialog.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, FormGroup, Typography } from "@mui/material";
|
||||||
|
import { SidebarUserObj } from "../sidebar/SidebarUser";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
open: boolean;
|
||||||
|
selectedValue: SidebarUserObj;
|
||||||
|
onClose: (value: SidebarUserObj) => void;
|
||||||
|
users: SidebarUserObj[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const CallFavouritesDialog: React.FC<Props> = ({ open, selectedValue, onClose, users }: Props) => {
|
||||||
|
const handleClose = () => {
|
||||||
|
onClose(selectedValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
onClose={handleClose}
|
||||||
|
open={open}
|
||||||
|
fullWidth
|
||||||
|
maxWidth="sm"
|
||||||
|
>
|
||||||
|
<DialogTitle>Select who to call:</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<FormControlLabel control={<Checkbox color="success" />} label="Select everyone" />
|
||||||
|
</DialogContent>
|
||||||
|
<DialogContent sx={{ height: "40vh" }} dividers>
|
||||||
|
<FormGroup>
|
||||||
|
{users.map((user) => (
|
||||||
|
<FormControlLabel key={user.id} control={<Checkbox color="success" />} label={user.name} />
|
||||||
|
))}
|
||||||
|
</FormGroup>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button color="success" onClick={handleClose}>
|
||||||
|
<Typography variant="button" color="black">Call</Typography>
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CallFavouritesDialog;
|
||||||
@ -2,8 +2,22 @@ import MeetingsPanel from "./MeetingsPanel";
|
|||||||
import ShortCuts from "./ShortCuts";
|
import ShortCuts from "./ShortCuts";
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
|
import { MeetingStatus, SidebarUserObj } from "../sidebar/SidebarUser";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
const Home: React.FC = () => {
|
const Home: React.FC = () => {
|
||||||
|
|
||||||
|
/* Temporary data - this is the same as what's in ProtectedRoute.tsx so it should not
|
||||||
|
be duplicated like this in the future (Route components were being weird when I tried
|
||||||
|
to pass it down from App.tsx) */
|
||||||
|
const [mockUsers] = useState<SidebarUserObj[]>([
|
||||||
|
{ id: 0, name: "Jincheng L.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
|
{ id: 1, name: "Matt B.", meetingStatus: MeetingStatus.IN_MEETING },
|
||||||
|
{ id: 2, name: "Taehee C.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 3, name: "Bob A.", meetingStatus: MeetingStatus.AWAY }
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="main-home">
|
<Container className="main-home">
|
||||||
<Grid container>
|
<Grid container>
|
||||||
@ -11,7 +25,7 @@ const Home: React.FC = () => {
|
|||||||
<MeetingsPanel />
|
<MeetingsPanel />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item sm={4}>
|
<Grid item sm={4}>
|
||||||
<ShortCuts />
|
<ShortCuts users={mockUsers}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -5,8 +5,27 @@ import CircleIcon from "@mui/icons-material/Circle";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
import { SidebarUserObj } from "../sidebar/SidebarUser";
|
||||||
|
import CallFavouritesDialog from "./CallFavouritesDialog";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
users: SidebarUserObj[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShortCuts: React.FC<Props> = ({ users }: Props) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [selectedValue, setSelectedValue] = useState(users[0]);
|
||||||
|
|
||||||
|
const handleClickOpen = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = (value: SidebarUserObj) => {
|
||||||
|
setOpen(false);
|
||||||
|
setSelectedValue(value);
|
||||||
|
};
|
||||||
|
|
||||||
const ShortCuts: React.FC = () => {
|
|
||||||
return (
|
return (
|
||||||
<div className="short-cuts" >
|
<div className="short-cuts" >
|
||||||
<Grid className="row-1" container spacing={1}>
|
<Grid className="row-1" container spacing={1}>
|
||||||
@ -25,9 +44,14 @@ const ShortCuts: React.FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid className="row-2" container spacing={1}>
|
<Grid className="row-2" container spacing={1}>
|
||||||
<Grid item sm={6}>
|
<Grid item sm={6}>
|
||||||
<Button className="tile">
|
<Button className="tile" onClick={handleClickOpen}>
|
||||||
<PhoneEnabledIcon className="icon" />
|
<PhoneEnabledIcon className="icon" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<CallFavouritesDialog
|
||||||
|
selectedValue={selectedValue}
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
users={users}/>
|
||||||
<Typography className="mylabel" sx={{ ml: 1 }}>Call Favourites</Typography>
|
<Typography className="mylabel" sx={{ ml: 1 }}>Call Favourites</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item sm={6}>
|
<Grid item sm={6}>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRef, useState, useEffect, useContext } from "react";
|
import { useState } from "react";
|
||||||
import { useLocation, Link, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { Stack } from "@mui/material";
|
import { Stack, Typography } from "@mui/material";
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -9,13 +9,16 @@ import zoomLogo from "../../assets/zoom.png";
|
|||||||
import LoginIcon from "@mui/icons-material/Login";
|
import LoginIcon from "@mui/icons-material/Login";
|
||||||
import useAuth from "../../hooks/useAuth";
|
import useAuth from "../../hooks/useAuth";
|
||||||
|
|
||||||
|
interface LocationState {
|
||||||
|
from: { pathname: string };
|
||||||
|
}
|
||||||
const Login: React.FC = () => {
|
const Login: React.FC = () => {
|
||||||
|
const setAuth = useAuth();
|
||||||
const { setAuth }: any = useAuth();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location: any = useLocation();
|
const location = useLocation();
|
||||||
const from = location.state?.from?.pathname || "/";
|
const state = location.state as LocationState;
|
||||||
|
const from = state?.from?.pathname || "/";
|
||||||
|
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
@ -34,8 +37,10 @@ const Login: React.FC = () => {
|
|||||||
|
|
||||||
const handleLogin = () => {
|
const handleLogin = () => {
|
||||||
if (username === "" && password === "") {
|
if (username === "" && password === "") {
|
||||||
setAuth({username: username, isLoggedIn: true});
|
// setAuth({username: username, isLoggedIn: true});
|
||||||
navigate(from, {replace: true});
|
setAuth["username"] = username;
|
||||||
|
setAuth["isLoggedIn"] = true;
|
||||||
|
navigate(from, { replace: true });
|
||||||
}
|
}
|
||||||
setUsername("");
|
setUsername("");
|
||||||
setPassword("");
|
setPassword("");
|
||||||
@ -44,18 +49,47 @@ const Login: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Container className="login">
|
<Container className="login">
|
||||||
<Stack className="grid-container" spacing={2}>
|
<Stack className="grid-container" spacing={2}>
|
||||||
<img className="login-logo" src={hsbcLogo} alt="HSBC Logo"/>
|
<img className="login-logo" src={hsbcLogo} alt="HSBC Logo" />
|
||||||
{/* <p ref={errRef} className={errMsg ? "errmsg" : "offscreen"} aria-live="assertive">{errMsg}</p> */}
|
{/* <p ref={errRef} className={errMsg ? "errmsg" : "offscreen"} aria-live="assertive">{errMsg}</p> */}
|
||||||
<TextField className="username-input" id="outlined-basic" label="Username" variant="outlined" placeholder="Username" onChange={(event) => {setUsername(event.target.value)}}/>
|
<TextField
|
||||||
<TextField className="password-input" id="outlined-basic" label="Password" variant="outlined" placeholder="Password" type="password" onChange={(event) => {setPassword(event.target.value)}}/>
|
className="username-input"
|
||||||
|
id="outlined-basic"
|
||||||
|
label="Username"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="Username"
|
||||||
|
onChange={(event) => {
|
||||||
|
setUsername(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
className="password-input"
|
||||||
|
id="outlined-basic"
|
||||||
|
label="Password"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="Password"
|
||||||
|
type="password"
|
||||||
|
onChange={(event) => {
|
||||||
|
setPassword(event.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Stack direction="row" justifyContent="space-between" spacing={2}>
|
<Stack direction="row" justifyContent="space-between" spacing={2}>
|
||||||
<a className="register-btn" href="#">Forgotten Your Password?</a>
|
<a className="register-btn" href="#">
|
||||||
<Button endIcon={<LoginIcon />} className="login-btn" variant="contained" type="submit" onClick={handleLogin}>Login</Button>
|
<Typography sx={{ ml: 1, mb: 1 }}>Forgot your password?</Typography>
|
||||||
|
</a>
|
||||||
|
<Button
|
||||||
|
endIcon={<LoginIcon />}
|
||||||
|
className="login-btn"
|
||||||
|
variant="contained"
|
||||||
|
type="submit"
|
||||||
|
onClick={handleLogin}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack direction="row" justifyContent="space-between" spacing={2}>
|
<Stack direction="row" justifyContent="space-between" spacing={2}>
|
||||||
<label>Login with</label>
|
<Typography sx={{ ml: 1 }}>Login with</Typography>
|
||||||
<a className="zoom-logo" href="#">
|
<a className="zoom-logo" href="#">
|
||||||
<img src={zoomLogo} alt="Zoom Logo"/>
|
<img src={zoomLogo} alt="Zoom Logo" />
|
||||||
</a>
|
</a>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@ -2,17 +2,24 @@ import { Dialog } from "@mui/material";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Body from "./meeting-details-components/Body";
|
import Body from "./meeting-details-components/Body";
|
||||||
import Header from "./meeting-details-components/Header";
|
import Header from "./meeting-details-components/Header";
|
||||||
|
import { useAppSelector, useAppDispatch } from "../../redux/hooks";
|
||||||
|
import {
|
||||||
|
close,
|
||||||
|
selectMeetingDetailsOpen,
|
||||||
|
} from "../../redux/slices/meetingDetailsOpenSlice";
|
||||||
|
|
||||||
interface Props {
|
const MeetingDetails: React.FC = () => {
|
||||||
open: boolean;
|
const meetingDetailsOpen = useAppSelector(selectMeetingDetailsOpen);
|
||||||
setOpen: (open: boolean) => void;
|
const dispatch = useAppDispatch();
|
||||||
}
|
|
||||||
|
|
||||||
const MeetingDetails: React.FC<Props> = (props) => {
|
|
||||||
return (
|
return (
|
||||||
<Dialog fullScreen open={props.open} onClose={() => props.setOpen(false)}>
|
<Dialog
|
||||||
<Header setOpen={props.setOpen} />
|
fullScreen
|
||||||
<Body />
|
open={meetingDetailsOpen.open}
|
||||||
|
onClose={() => dispatch(close())}
|
||||||
|
>
|
||||||
|
<Header meeting={meetingDetailsOpen.meeting} />
|
||||||
|
<Body meeting={meetingDetailsOpen.meeting} />
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,8 +8,13 @@ import {
|
|||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
||||||
|
import DetailedMeeting from "../../../api-bodies/DetailedMeeting";
|
||||||
|
|
||||||
const Body: React.FC = () => {
|
interface Props {
|
||||||
|
meeting: DetailedMeeting | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Body: React.FC<Props> = () => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@ -1,17 +1,22 @@
|
|||||||
import { AppBar, Button, IconButton, Toolbar, Typography } from "@mui/material";
|
import { AppBar, Button, IconButton, Toolbar, Typography } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { useAppDispatch } from "../../../redux/hooks";
|
||||||
|
import { close } from "../../../redux/slices/meetingDetailsOpenSlice";
|
||||||
|
import DetailedMeeting from "../../../api-bodies/DetailedMeeting";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setOpen: (open: boolean) => void;
|
meeting: DetailedMeeting | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Header: React.FC<Props> = (props) => {
|
const Header: React.FC<Props> = (props) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBar sx={{ position: "relative" }}>
|
<AppBar sx={{ position: "relative" }}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography variant="h6" sx={{ flexGrow: 1 }}>
|
<Typography variant="h6" sx={{ flexGrow: 1 }}>
|
||||||
Kanban Meeting
|
{props.meeting !== null ? props.meeting.topic : null}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button variant="contained" color="secondary">
|
<Button variant="contained" color="secondary">
|
||||||
Join
|
Join
|
||||||
@ -23,7 +28,7 @@ const Header: React.FC<Props> = (props) => {
|
|||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="close"
|
aria-label="close"
|
||||||
onClick={() => props.setOpen(false)}
|
onClick={() => dispatch(close())}
|
||||||
sx={{ ml: 1 }}
|
sx={{ ml: 1 }}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
import { createContext, useState } from "react";
|
import { createContext, useState } from "react";
|
||||||
|
|
||||||
const AuthContext = createContext({});
|
interface loginInfo {
|
||||||
|
username: string;
|
||||||
export const AuthProvider = ({ children }: {children: any}) => {
|
isLoggedIn: boolean;
|
||||||
const [auth, setAuth] = useState({});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AuthContext.Provider value={{ auth, setAuth }}>
|
|
||||||
{children}
|
|
||||||
</AuthContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AuthContext = createContext<loginInfo>({
|
||||||
|
username: "",
|
||||||
|
isLoggedIn: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const [auth] = useState<loginInfo>({ username: "", isLoggedIn: false });
|
||||||
|
|
||||||
|
return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
export default AuthContext;
|
export default AuthContext;
|
||||||
@ -1,8 +1,13 @@
|
|||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import AuthContext from "../context/AuthProvider";
|
import AuthContext from "../context/AuthProvider";
|
||||||
|
|
||||||
const useAuth = () => {
|
interface loginInfo {
|
||||||
return useContext(AuthContext);
|
username: string;
|
||||||
|
isLoggedIn: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useAuth = () => {
|
||||||
|
return useContext<loginInfo>(AuthContext);
|
||||||
|
};
|
||||||
|
|
||||||
export default useAuth;
|
export default useAuth;
|
||||||
@ -1,12 +1,25 @@
|
|||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import "./style/App.css";
|
import "./style/App.css";
|
||||||
import { AuthProvider } from './context/AuthProvider';
|
import { AuthProvider } from "./context/AuthProvider";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
import { store } from "./redux/store";
|
||||||
|
import { fetchFavorites } from "./redux/slices/favoritesSlice";
|
||||||
|
import { fetchTeam } from "./redux/slices/teamSlice";
|
||||||
|
import { fetchMeetings } from "./redux/slices/meetingsSlice";
|
||||||
|
import { fetchPeople } from "./redux/slices/peopleSlice";
|
||||||
|
|
||||||
const Index:React.FC = () => {
|
store.dispatch(fetchPeople(""));
|
||||||
|
store.dispatch(fetchFavorites(""));
|
||||||
|
store.dispatch(fetchTeam(""));
|
||||||
|
store.dispatch(fetchMeetings(""));
|
||||||
|
|
||||||
|
const Index: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<App />
|
<Provider store={store}>
|
||||||
|
<App />
|
||||||
|
</Provider>
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
6
src/redux/hooks.tsx
Normal file
6
src/redux/hooks.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
|
||||||
|
import type { RootState, AppDispatch } from "./store";
|
||||||
|
|
||||||
|
// Use throughout your app instead of plain `useDispatch` and `useSelector`
|
||||||
|
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
||||||
|
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||||
55
src/redux/slices/favoritesSlice.tsx
Normal file
55
src/redux/slices/favoritesSlice.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
|
||||||
|
interface FavoritesState {
|
||||||
|
favorites: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: FavoritesState = {
|
||||||
|
favorites: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const favoritesSlice = createSlice({
|
||||||
|
name: "favorites",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers(builder) {
|
||||||
|
builder
|
||||||
|
.addCase(fetchFavorites.fulfilled, (state, action) => {
|
||||||
|
state.favorites = action.payload;
|
||||||
|
})
|
||||||
|
.addCase(addFavorite.fulfilled, (state, action) => {
|
||||||
|
state.favorites.push(action.payload);
|
||||||
|
})
|
||||||
|
.addCase(removeFavorite.fulfilled, (state, action) => {
|
||||||
|
const index = state.favorites.indexOf(action.payload);
|
||||||
|
state.favorites.splice(index, 1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchFavorites = createAsyncThunk(
|
||||||
|
"favorites/fetchFavorites",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
// !!!
|
||||||
|
console.log(uuid);
|
||||||
|
return ["2", "4"];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export const addFavorite = createAsyncThunk(
|
||||||
|
"favorites/addFavorite",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export const removeFavorite = createAsyncThunk(
|
||||||
|
"favorites/removeFavorite",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export const selectFavorites = (state: RootState) => state.favorites.favorites;
|
||||||
|
export default favoritesSlice.reducer;
|
||||||
33
src/redux/slices/meetingDetailsOpenSlice.tsx
Normal file
33
src/redux/slices/meetingDetailsOpenSlice.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
|
||||||
|
interface MeetingDetailsOpenState {
|
||||||
|
open: boolean;
|
||||||
|
meeting: DetailedMeeting | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: MeetingDetailsOpenState = {
|
||||||
|
open: false,
|
||||||
|
meeting: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const meetingDetailsOpenSlice = createSlice({
|
||||||
|
name: "meetingDetailsOpen",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
open: (state, action) => {
|
||||||
|
state.open = true;
|
||||||
|
state.meeting = action.payload;
|
||||||
|
},
|
||||||
|
close: (state) => {
|
||||||
|
state.open = false;
|
||||||
|
state.meeting = null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { open, close } = meetingDetailsOpenSlice.actions;
|
||||||
|
export const selectMeetingDetailsOpen = (state: RootState) =>
|
||||||
|
state.meetingDetailsOpen;
|
||||||
|
export default meetingDetailsOpenSlice.reducer;
|
||||||
41
src/redux/slices/meetingsSlice.tsx
Normal file
41
src/redux/slices/meetingsSlice.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||||
|
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
import { meetings } from "../../api-bodies/MockData";
|
||||||
|
|
||||||
|
interface MeetingsState {
|
||||||
|
meetings: DetailedMeeting[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: MeetingsState = {
|
||||||
|
meetings: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const meetingsSlice = createSlice({
|
||||||
|
name: "meetings",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers(builder) {
|
||||||
|
builder.addCase(fetchMeetings.fulfilled, (state, action) => {
|
||||||
|
return action.payload;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchMeetings = createAsyncThunk(
|
||||||
|
"meetings/fetchMeetings",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
// !!!
|
||||||
|
console.log(uuid);
|
||||||
|
return { meetings: meetings };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectMeetings = (state: RootState) => state.meetings.meetings;
|
||||||
|
export const selectUserUpcomingMeetings = (state: RootState, uuid: string) => {
|
||||||
|
return state.meetings.meetings.filter((meeting) =>
|
||||||
|
meeting.registrantIds.includes(uuid)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default meetingsSlice.reducer;
|
||||||
40
src/redux/slices/peopleSlice.tsx
Normal file
40
src/redux/slices/peopleSlice.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||||
|
import UserLite from "../../api-bodies/UserLite";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
import { people } from "../../api-bodies/MockData";
|
||||||
|
|
||||||
|
interface PeopleState {
|
||||||
|
people: UserLite[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: PeopleState = {
|
||||||
|
people: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const peopleSlice = createSlice({
|
||||||
|
name: "people",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers(builder) {
|
||||||
|
builder.addCase(fetchPeople.fulfilled, (state, action) => {
|
||||||
|
console.log(action.payload);
|
||||||
|
state.people = action.payload;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchPeople = createAsyncThunk(
|
||||||
|
"people/fetchPeople",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
// !!!
|
||||||
|
console.log(uuid);
|
||||||
|
return people;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectFavoritesJSON = (state: RootState, favorites: string[]) => {
|
||||||
|
return state.people.people.filter((p) => favorites.includes(p.uuid));
|
||||||
|
};
|
||||||
|
export const selectTeamJSON = (state: RootState) => state.people.people;
|
||||||
|
export default peopleSlice.reducer;
|
||||||
41
src/redux/slices/teamSlice.tsx
Normal file
41
src/redux/slices/teamSlice.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
import { team } from "../../api-bodies/MockData";
|
||||||
|
|
||||||
|
interface TeamState {
|
||||||
|
user: string | null;
|
||||||
|
manager: string | null;
|
||||||
|
sameManager: string[];
|
||||||
|
directReports: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: TeamState = {
|
||||||
|
user: null,
|
||||||
|
manager: null,
|
||||||
|
sameManager: [],
|
||||||
|
directReports: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const teamSlice = createSlice({
|
||||||
|
name: "team",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers(builder) {
|
||||||
|
builder.addCase(fetchTeam.fulfilled, (state, action) => {
|
||||||
|
return action.payload;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchTeam = createAsyncThunk(
|
||||||
|
"team/fetchTeam",
|
||||||
|
async (uuid: string) => {
|
||||||
|
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||||
|
// !!!
|
||||||
|
console.log(uuid);
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectTeam = (state: RootState) => state.team;
|
||||||
|
export default teamSlice.reducer;
|
||||||
19
src/redux/store.tsx
Normal file
19
src/redux/store.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { configureStore } from "@reduxjs/toolkit";
|
||||||
|
import meetingDetailsOpenReducer from "./slices/meetingDetailsOpenSlice";
|
||||||
|
import favoritesReducer from "./slices/favoritesSlice";
|
||||||
|
import teamReducer from "./slices/teamSlice";
|
||||||
|
import meetingsReducer from "./slices/meetingsSlice";
|
||||||
|
import peopleReducer from "./slices/peopleSlice";
|
||||||
|
|
||||||
|
export const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
meetingDetailsOpen: meetingDetailsOpenReducer,
|
||||||
|
favorites: favoritesReducer,
|
||||||
|
team: teamReducer,
|
||||||
|
meetings: meetingsReducer,
|
||||||
|
people: peopleReducer,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
export type AppDispatch = typeof store.dispatch;
|
||||||
Reference in New Issue
Block a user