From 3320d0d932719572df7716c199dee1b2eadd73b3 Mon Sep 17 00:00:00 2001 From: Taehee Choi Date: Sun, 13 Mar 2022 11:56:47 -0700 Subject: [PATCH 1/3] initial redux setup --- package-lock.json | 186 ++++++++++++++++++ package.json | 2 + src/App.tsx | 9 +- src/components/contacts/Contacts.tsx | 11 +- .../contacts/contacts-components/Body.tsx | 6 +- .../body-components/LowerBody.tsx | 12 +- .../meeting-details/MeetingDetails.tsx | 17 +- .../meeting-details-components/Header.tsx | 10 +- src/index.tsx | 10 +- src/redux/slices/meetingDetailsOpenSlice.tsx | 28 +++ src/redux/store.tsx | 11 ++ 11 files changed, 259 insertions(+), 43 deletions(-) create mode 100644 src/redux/slices/meetingDetailsOpenSlice.tsx create mode 100644 src/redux/store.tsx diff --git a/package-lock.json b/package-lock.json index c1f606e..2b535d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,10 @@ "@emotion/styled": "^11.8.1", "@mui/icons-material": "^5.4.2", "@mui/material": "^5.4.3", + "@reduxjs/toolkit": "^1.8.0", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-redux": "^7.2.6", "react-router-dom": "^6.2.1" }, "devDependencies": { @@ -2205,6 +2207,29 @@ "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/@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", @@ -2560,6 +2585,15 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "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": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -2654,6 +2688,17 @@ "@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": { "version": "5.1.18", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", @@ -4552,6 +4597,7 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", + "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -7707,6 +7753,12 @@ "dev": true, "dependencies": { "imagemin": "^7.0.1", + "imagemin-gifsicle": "^7.0.0", + "imagemin-mozjpeg": "^9.0.0", + "imagemin-optipng": "^8.0.0", + "imagemin-pngquant": "^9.0.2", + "imagemin-svgo": "^9.0.0", + "imagemin-webp": "^7.0.0", "loader-utils": "^2.0.0", "object-assign": "^4.1.1", "schema-utils": "^2.7.1" @@ -8163,6 +8215,15 @@ "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": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -10470,6 +10531,35 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "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": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz", @@ -10548,6 +10638,22 @@ "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": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -10698,6 +10804,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "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": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -14247,6 +14358,17 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", "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" + } + }, "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", @@ -14498,6 +14620,15 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "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": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -14592,6 +14723,17 @@ "@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": { "version": "5.1.18", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", @@ -18827,6 +18969,11 @@ "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": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -20521,6 +20668,26 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "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": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz", @@ -20582,6 +20749,20 @@ "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": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -20701,6 +20882,11 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", diff --git a/package.json b/package.json index 2884ba1..21ebbf0 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "@emotion/styled": "^11.8.1", "@mui/icons-material": "^5.4.2", "@mui/material": "^5.4.3", + "@reduxjs/toolkit": "^1.8.0", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-redux": "^7.2.6", "react-router-dom": "^6.2.1" }, "scripts": { diff --git a/src/App.tsx b/src/App.tsx index 8f8e4e6..51159e7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,8 +15,6 @@ import Theme from "./Theme"; import "./style/App.css"; const App: React.FC = () => { - const [meetingInfoOpen, setMeetingInfoOpen] = useState(false); - return ( @@ -24,15 +22,12 @@ const App: React.FC = () => { } /> }> } /> - } - /> + } /> } /> - + ); }; diff --git a/src/components/contacts/Contacts.tsx b/src/components/contacts/Contacts.tsx index c95afe8..72df34b 100644 --- a/src/components/contacts/Contacts.tsx +++ b/src/components/contacts/Contacts.tsx @@ -5,11 +5,7 @@ import Body from "./contacts-components/Body"; import ContactInfo from "./ContactInfo"; import Sidebar from "./contacts-components/Sidebar"; -interface Props { - setMeetingInfoOpen: (open: boolean) => void; -} - -const Contacts: React.FC = (props) => { +const Contacts: React.FC = () => { const [contactSelected, setContactSelected] = React.useState(null); @@ -17,10 +13,7 @@ const Contacts: React.FC = (props) => { {contactSelected !== null ? ( - + ) : null} ); diff --git a/src/components/contacts/contacts-components/Body.tsx b/src/components/contacts/contacts-components/Body.tsx index fd4de4a..a42fe35 100644 --- a/src/components/contacts/contacts-components/Body.tsx +++ b/src/components/contacts/contacts-components/Body.tsx @@ -6,7 +6,6 @@ import ContactInfo from "../ContactInfo"; interface Props { contactSelected: ContactInfo; - setMeetingInfoOpen: (open: boolean) => void; } const Body: React.FC = (props) => { @@ -21,10 +20,7 @@ const Body: React.FC = (props) => { > - + ); }; diff --git a/src/components/contacts/contacts-components/body-components/LowerBody.tsx b/src/components/contacts/contacts-components/body-components/LowerBody.tsx index a43d74f..ffeac31 100644 --- a/src/components/contacts/contacts-components/body-components/LowerBody.tsx +++ b/src/components/contacts/contacts-components/body-components/LowerBody.tsx @@ -1,6 +1,7 @@ import { Box, Button, List, Typography } from "@mui/material"; import React from "react"; -import ContactInfo from "../../ContactInfo"; +import { useDispatch } from "react-redux"; +import { open } from "../../../../redux/slices/meetingDetailsOpenSlice"; const meetings: { name: string; duration: string }[] = [ { name: "Kanban Meeting", duration: "10:45 am - 11:45 am" }, @@ -10,12 +11,9 @@ const meetings: { name: string; duration: string }[] = [ { name: "Some kind of Meeting", duration: "10:45 am - 11:45 am" }, ]; -interface Props { - contactInfo: ContactInfo; - setMeetingInfoOpen: (open: boolean) => void; -} +const LowerBody: React.FC = () => { + const dispatch = useDispatch(); -const LowerBody: React.FC = (props) => { return ( = (props) => { diff --git a/src/components/meeting-details/MeetingDetails.tsx b/src/components/meeting-details/MeetingDetails.tsx index dcca058..44bb176 100644 --- a/src/components/meeting-details/MeetingDetails.tsx +++ b/src/components/meeting-details/MeetingDetails.tsx @@ -2,16 +2,19 @@ import { Dialog } from "@mui/material"; import React from "react"; import Body from "./meeting-details-components/Body"; import Header from "./meeting-details-components/Header"; +import { useSelector, useDispatch } from "react-redux"; +import { + close, + selectMeetingDetailsOpen, +} from "../../redux/slices/meetingDetailsOpenSlice"; -interface Props { - open: boolean; - setOpen: (open: boolean) => void; -} +const MeetingDetails: React.FC = () => { + const open = useSelector(selectMeetingDetailsOpen); + const dispatch = useDispatch(); -const MeetingDetails: React.FC = (props) => { return ( - props.setOpen(false)}> -
+ dispatch(close())}> +
); diff --git a/src/components/meeting-details/meeting-details-components/Header.tsx b/src/components/meeting-details/meeting-details-components/Header.tsx index 5f40cd8..5b4b2fb 100644 --- a/src/components/meeting-details/meeting-details-components/Header.tsx +++ b/src/components/meeting-details/meeting-details-components/Header.tsx @@ -1,12 +1,12 @@ import { AppBar, Button, IconButton, Toolbar, Typography } from "@mui/material"; import React from "react"; import CloseIcon from "@mui/icons-material/Close"; +import { useDispatch } from "react-redux"; +import { close } from "../../../redux/slices/meetingDetailsOpenSlice"; -interface Props { - setOpen: (open: boolean) => void; -} +const Header: React.FC = () => { + const dispatch = useDispatch(); -const Header: React.FC = (props) => { return ( @@ -23,7 +23,7 @@ const Header: React.FC = (props) => { edge="start" color="inherit" aria-label="close" - onClick={() => props.setOpen(false)} + onClick={() => dispatch(close())} sx={{ ml: 1 }} > diff --git a/src/index.tsx b/src/index.tsx index d8f9587..802c9d8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,16 @@ import ReactDOM from "react-dom"; import App from "./App"; import "./style/App.css"; -import { AuthProvider } from './context/AuthProvider'; +import { AuthProvider } from "./context/AuthProvider"; +import { Provider } from "react-redux"; +import { store } from "./redux/store"; -const Index:React.FC = () => { +const Index: React.FC = () => { return ( - + + + ); }; diff --git a/src/redux/slices/meetingDetailsOpenSlice.tsx b/src/redux/slices/meetingDetailsOpenSlice.tsx new file mode 100644 index 0000000..6594543 --- /dev/null +++ b/src/redux/slices/meetingDetailsOpenSlice.tsx @@ -0,0 +1,28 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { RootState } from "../store"; + +interface MeetingDetailsOpenState { + open: boolean; +} + +const initialState: MeetingDetailsOpenState = { + open: false, +}; + +export const meetingDetailsOpenSlice = createSlice({ + name: "meetingDetailsOpen", + initialState, + reducers: { + open: (state) => { + state.open = true; + }, + close: (state) => { + state.open = false; + }, + }, +}); + +export const { open, close } = meetingDetailsOpenSlice.actions; +export const selectMeetingDetailsOpen = (state: RootState) => + state.meetingDetailsOpen.open; +export default meetingDetailsOpenSlice.reducer; diff --git a/src/redux/store.tsx b/src/redux/store.tsx new file mode 100644 index 0000000..75cffc1 --- /dev/null +++ b/src/redux/store.tsx @@ -0,0 +1,11 @@ +import { configureStore } from "@reduxjs/toolkit"; +import meetingDetailsOpenReducer from "./slices/meetingDetailsOpenSlice"; + +export const store = configureStore({ + reducer: { + meetingDetailsOpen: meetingDetailsOpenReducer, + }, +}); + +export type RootState = ReturnType; +export type AppDispatch = typeof store.dispatch; From 52f76f82096e00398b6a43dc8d74190bdd97b7b1 Mon Sep 17 00:00:00 2001 From: Taehee Choi Date: Sun, 13 Mar 2022 11:58:14 -0700 Subject: [PATCH 2/3] fix lint warnings --- src/App.tsx | 2 +- src/ProtectedRoute.tsx | 36 ++++++++++++------------ src/components/login/Login.tsx | 50 ++++++++++++++++++++++++++-------- src/context/AuthProvider.tsx | 14 +++++----- src/hooks/useAuth.tsx | 4 +-- 5 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 51159e7..1595743 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import "./styles.css"; diff --git a/src/ProtectedRoute.tsx b/src/ProtectedRoute.tsx index e3a9edd..ad67baa 100644 --- a/src/ProtectedRoute.tsx +++ b/src/ProtectedRoute.tsx @@ -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 Navbar from "./components/navbar/Navbar"; import Sidebar from "./components/sidebar/Sidebar"; -import React, {useState} from "react"; +import React, { useState } from "react"; import { MeetingStatus, SidebarUserObj, } from "./components/sidebar/SidebarUser"; -import {Box} from "@mui/material"; +import { Box } from "@mui/material"; const ProtectedRoute = () => { const { auth }: any = useAuth(); const location = useLocation(); - const [meetingInfoOpen, setMeetingInfoOpen] = useState(false); /* Temporary data */ const [sidebarUsers] = useState([ { id: 0, name: "Jincheng L.", meetingStatus: MeetingStatus.ONLINE }, @@ -38,22 +37,21 @@ const ProtectedRoute = () => { { id: 19, name: "Bob Q.", meetingStatus: MeetingStatus.ONLINE }, { id: 20, name: "Bob R.", meetingStatus: MeetingStatus.ONLINE }, ]); - return ( - auth?.isLoggedIn - ? - <> - - - - - - - - + return auth?.isLoggedIn ? ( + <> + + + + - - : + + + + + + ) : ( + ); }; -export default ProtectedRoute; \ No newline at end of file +export default ProtectedRoute; diff --git a/src/components/login/Login.tsx b/src/components/login/Login.tsx index 5ff4a66..e1b25b1 100644 --- a/src/components/login/Login.tsx +++ b/src/components/login/Login.tsx @@ -1,5 +1,5 @@ -import { useRef, useState, useEffect, useContext } from "react"; -import { useLocation, Link, useNavigate } from "react-router-dom"; +import { useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; import { Stack, Typography } from "@mui/material"; import Container from "@mui/material/Container"; import TextField from "@mui/material/TextField"; @@ -10,7 +10,6 @@ import LoginIcon from "@mui/icons-material/Login"; import useAuth from "../../hooks/useAuth"; const Login: React.FC = () => { - const { setAuth }: any = useAuth(); const navigate = useNavigate(); @@ -34,8 +33,8 @@ const Login: React.FC = () => { const handleLogin = () => { if (username === "" && password === "") { - setAuth({username: username, isLoggedIn: true}); - navigate(from, {replace: true}); + setAuth({ username: username, isLoggedIn: true }); + navigate(from, { replace: true }); } setUsername(""); setPassword(""); @@ -44,25 +43,52 @@ const Login: React.FC = () => { return ( - HSBC Logo + HSBC Logo {/*

{errMsg}

*/} - {setUsername(event.target.value)}}/> - {setPassword(event.target.value)}}/> + { + setUsername(event.target.value); + }} + /> + { + setPassword(event.target.value); + }} + /> Forgot your password? - + Login with - Zoom Logo + Zoom Logo
); }; - -export default Login; \ No newline at end of file + +export default Login; diff --git a/src/context/AuthProvider.tsx b/src/context/AuthProvider.tsx index cb661da..8411ab4 100644 --- a/src/context/AuthProvider.tsx +++ b/src/context/AuthProvider.tsx @@ -3,13 +3,13 @@ import { createContext, useState } from "react"; const AuthContext = createContext({}); export const AuthProvider = ({ children }: {children: any}) => { - const [auth, setAuth] = useState({}); + const [auth, setAuth] = useState({}); - return ( - - {children} - - ) -} + return ( + + {children} + + ); +}; export default AuthContext; \ No newline at end of file diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index d1fb072..e1d0b6d 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -2,7 +2,7 @@ import { useContext } from "react"; import AuthContext from "../context/AuthProvider"; const useAuth = () => { - return useContext(AuthContext); -} + return useContext(AuthContext); +}; export default useAuth; \ No newline at end of file From 20a4d5dabf79ca6ba6016c620a35df8841f4627e Mon Sep 17 00:00:00 2001 From: Taehee Choi Date: Sun, 13 Mar 2022 18:16:19 -0700 Subject: [PATCH 3/3] initial redux set up --- src/api-bodies/MockData.tsx | 86 +++++++++++++++++++ src/components/contacts/ContactInfo.tsx | 8 -- src/components/contacts/Contacts.tsx | 7 +- src/components/contacts/Utils.tsx | 9 +- .../contacts/contacts-components/Body.tsx | 6 +- .../contacts/contacts-components/Sidebar.tsx | 39 +++++---- .../body-components/LowerBody.tsx | 31 ++++--- .../body-components/UpperBody.tsx | 9 +- .../sidebar-components/ContactItem.tsx | 11 +-- .../meeting-details/MeetingDetails.tsx | 16 ++-- .../meeting-details-components/Body.tsx | 7 +- .../meeting-details-components/Header.tsx | 13 ++- src/index.tsx | 9 ++ src/redux/hooks.tsx | 6 ++ src/redux/slices/favoritesSlice.tsx | 55 ++++++++++++ src/redux/slices/meetingDetailsOpenSlice.tsx | 9 +- src/redux/slices/meetingsSlice.tsx | 41 +++++++++ src/redux/slices/peopleSlice.tsx | 40 +++++++++ src/redux/slices/teamSlice.tsx | 41 +++++++++ src/redux/store.tsx | 8 ++ 20 files changed, 384 insertions(+), 67 deletions(-) create mode 100644 src/api-bodies/MockData.tsx delete mode 100644 src/components/contacts/ContactInfo.tsx create mode 100644 src/redux/hooks.tsx create mode 100644 src/redux/slices/favoritesSlice.tsx create mode 100644 src/redux/slices/meetingsSlice.tsx create mode 100644 src/redux/slices/peopleSlice.tsx create mode 100644 src/redux/slices/teamSlice.tsx diff --git a/src/api-bodies/MockData.tsx b/src/api-bodies/MockData.tsx new file mode 100644 index 0000000..5b1ab73 --- /dev/null +++ b/src/api-bodies/MockData.tsx @@ -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 }; diff --git a/src/components/contacts/ContactInfo.tsx b/src/components/contacts/ContactInfo.tsx deleted file mode 100644 index 27646b6..0000000 --- a/src/components/contacts/ContactInfo.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import Status from "./Status"; - -interface ContactInfo { - name: string; - status: Status; -} - -export default ContactInfo; diff --git a/src/components/contacts/Contacts.tsx b/src/components/contacts/Contacts.tsx index 72df34b..e533db4 100644 --- a/src/components/contacts/Contacts.tsx +++ b/src/components/contacts/Contacts.tsx @@ -2,12 +2,13 @@ import { Box } from "@mui/material"; import React from "react"; import Body from "./contacts-components/Body"; -import ContactInfo from "./ContactInfo"; import Sidebar from "./contacts-components/Sidebar"; +import UserLite from "../../api-bodies/UserLite"; const Contacts: React.FC = () => { - const [contactSelected, setContactSelected] = - React.useState(null); + const [contactSelected, setContactSelected] = React.useState( + null + ); return ( diff --git a/src/components/contacts/Utils.tsx b/src/components/contacts/Utils.tsx index e5424d8..bedc302 100644 --- a/src/components/contacts/Utils.tsx +++ b/src/components/contacts/Utils.tsx @@ -1,3 +1,4 @@ +import DetailedMeeting from "../../api-bodies/DetailedMeeting"; import Status from "./Status"; 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 }; diff --git a/src/components/contacts/contacts-components/Body.tsx b/src/components/contacts/contacts-components/Body.tsx index a42fe35..bb9f5ce 100644 --- a/src/components/contacts/contacts-components/Body.tsx +++ b/src/components/contacts/contacts-components/Body.tsx @@ -2,10 +2,10 @@ import { Box, Toolbar } from "@mui/material"; import React from "react"; import UpperBody from "./body-components/UpperBody"; import LowerBody from "./body-components/LowerBody"; -import ContactInfo from "../ContactInfo"; +import UserLite from "../../../api-bodies/UserLite"; interface Props { - contactSelected: ContactInfo; + contactSelected: UserLite; } const Body: React.FC = (props) => { @@ -20,7 +20,7 @@ const Body: React.FC = (props) => { > - + ); }; diff --git a/src/components/contacts/contacts-components/Sidebar.tsx b/src/components/contacts/contacts-components/Sidebar.tsx index f4007f4..eecf63c 100644 --- a/src/components/contacts/contacts-components/Sidebar.tsx +++ b/src/components/contacts/contacts-components/Sidebar.tsx @@ -9,19 +9,17 @@ import { } from "@mui/material"; import React from "react"; import { ExpandLess, ExpandMore } from "@mui/icons-material"; -import ContactInfo from "../ContactInfo"; -import Status from "../Status"; import ContactItem from "./sidebar-components/ContactItem"; - -const contacts: ContactInfo[] = [ - { name: "Taehee ...", status: Status.Online }, - { name: "Jincheng ...", status: Status.Offline }, - { name: "Mathew ...", status: Status.InMeeting }, - { name: "Esteban ...", status: Status.Away }, -]; +import { useAppSelector } from "../../../redux/hooks"; +import { + selectFavoritesJSON, + selectTeamJSON, +} from "../../../redux/slices/peopleSlice"; +import { selectFavorites } from "../../../redux/slices/favoritesSlice"; +import UserLite from "../../../api-bodies/UserLite"; interface Props { - setContactSelected: (contactInfo: ContactInfo) => void; + setContactSelected: (contactInfo: UserLite) => void; } const sidebarWidth = 240; @@ -30,6 +28,12 @@ const Sidebar: React.FC = (props) => { const [favoritesOpen, setFavoritesOpen] = React.useState(true); const [teamOpen, setTeamOpen] = React.useState(false); + const favorites = useAppSelector(selectFavorites); + const favoritesJSON = useAppSelector((state) => + selectFavoritesJSON(state, favorites) + ); + const teamJSON = useAppSelector(selectTeamJSON); + return ( = (props) => { setFavoritesOpen(!favoritesOpen)}> {favoritesOpen ? : } - + - {contacts.map((contact, i) => ( + {favoritesJSON.map((favorite, i) => ( @@ -65,13 +72,13 @@ const Sidebar: React.FC = (props) => { setTeamOpen(!teamOpen)}> {teamOpen ? : } - + - {contacts.map((contact, i) => ( + {teamJSON.map((member, i) => ( diff --git a/src/components/contacts/contacts-components/body-components/LowerBody.tsx b/src/components/contacts/contacts-components/body-components/LowerBody.tsx index ffeac31..824c7a6 100644 --- a/src/components/contacts/contacts-components/body-components/LowerBody.tsx +++ b/src/components/contacts/contacts-components/body-components/LowerBody.tsx @@ -1,18 +1,21 @@ import { Box, Button, List, Typography } from "@mui/material"; import React from "react"; -import { useDispatch } from "react-redux"; +import UserLite from "../../../../api-bodies/UserLite"; +import { useAppSelector, useAppDispatch } from "../../../../redux/hooks"; import { open } from "../../../../redux/slices/meetingDetailsOpenSlice"; +import { selectUserUpcomingMeetings } from "../../../../redux/slices/meetingsSlice"; +import { getMeetingDuration } from "../../Utils"; -const meetings: { name: string; duration: string }[] = [ - { name: "Kanban Meeting", duration: "10:45 am - 11:45 am" }, - { name: "Design Meeting", duration: "10:45 am - 11:45 am" }, - { 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 { + contactInfo: UserLite; +} -const LowerBody: React.FC = () => { - const dispatch = useDispatch(); +const LowerBody: React.FC = (props) => { + const dispatch = useAppDispatch(); + + const meetings = useAppSelector((state) => + selectUserUpcomingMeetings(state, props.contactInfo.uuid) + ); return ( { - {meeting.duration} + + {getMeetingDuration(meeting)} + ))} diff --git a/src/components/contacts/contacts-components/body-components/UpperBody.tsx b/src/components/contacts/contacts-components/body-components/UpperBody.tsx index 18ead7a..39ad22f 100644 --- a/src/components/contacts/contacts-components/body-components/UpperBody.tsx +++ b/src/components/contacts/contacts-components/body-components/UpperBody.tsx @@ -3,11 +3,12 @@ import React from "react"; import PhoneIcon from "@mui/icons-material/Phone"; import VideocamIcon from "@mui/icons-material/Videocam"; import GroupsIcon from "@mui/icons-material/Groups"; -import ContactInfo from "../../ContactInfo"; import AddIcon from "@mui/icons-material/Add"; +import Status from "../../Status"; +import UserLite from "../../../../api-bodies/UserLite"; interface Props { - contactInfo: ContactInfo; + contactInfo: UserLite; } const UpperBody: React.FC = (props) => { @@ -63,9 +64,7 @@ const UpperBody: React.FC = (props) => {
- - {props.contactInfo.status} - + {Status.Online} MeetingName-1372 diff --git a/src/components/contacts/contacts-components/sidebar-components/ContactItem.tsx b/src/components/contacts/contacts-components/sidebar-components/ContactItem.tsx index c8d9e48..2b78288 100644 --- a/src/components/contacts/contacts-components/sidebar-components/ContactItem.tsx +++ b/src/components/contacts/contacts-components/sidebar-components/ContactItem.tsx @@ -2,12 +2,13 @@ import { ListItemButton, ListItemIcon, ListItemText } from "@mui/material"; import React from "react"; import PersonOutlineIcon from "@mui/icons-material/PersonOutline"; import CircleIcon from "@mui/icons-material/Circle"; -import ContactInfo from "../../ContactInfo"; import { returnStatusColor } from "../../Utils"; +import UserLite from "../../../../api-bodies/UserLite"; +import Status from "../../Status"; interface Props { - contactInfo: ContactInfo; - setContactSelected: (contactInfo: ContactInfo) => void; + contactInfo: UserLite; + setContactSelected: (contactInfo: UserLite) => void; } const ContactItem: React.FC = (props) => { @@ -22,10 +23,10 @@ const ContactItem: React.FC = (props) => { - + ); }; diff --git a/src/components/meeting-details/MeetingDetails.tsx b/src/components/meeting-details/MeetingDetails.tsx index 44bb176..0703c24 100644 --- a/src/components/meeting-details/MeetingDetails.tsx +++ b/src/components/meeting-details/MeetingDetails.tsx @@ -2,20 +2,24 @@ import { Dialog } from "@mui/material"; import React from "react"; import Body from "./meeting-details-components/Body"; import Header from "./meeting-details-components/Header"; -import { useSelector, useDispatch } from "react-redux"; +import { useAppSelector, useAppDispatch } from "../../redux/hooks"; import { close, selectMeetingDetailsOpen, } from "../../redux/slices/meetingDetailsOpenSlice"; const MeetingDetails: React.FC = () => { - const open = useSelector(selectMeetingDetailsOpen); - const dispatch = useDispatch(); + const meetingDetailsOpen = useAppSelector(selectMeetingDetailsOpen); + const dispatch = useAppDispatch(); return ( - dispatch(close())}> -
- + dispatch(close())} + > +
+
); }; diff --git a/src/components/meeting-details/meeting-details-components/Body.tsx b/src/components/meeting-details/meeting-details-components/Body.tsx index 632ac39..e253b82 100644 --- a/src/components/meeting-details/meeting-details-components/Body.tsx +++ b/src/components/meeting-details/meeting-details-components/Body.tsx @@ -8,8 +8,13 @@ import { } from "@mui/material"; import React from "react"; 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 = () => { return ( { - const dispatch = useDispatch(); +interface Props { + meeting: DetailedMeeting | null; +} + +const Header: React.FC = (props) => { + const dispatch = useAppDispatch(); return ( - Kanban Meeting + {props.meeting !== null ? props.meeting.topic : null}