redux updates

This commit is contained in:
Taehee Choi 2022-03-15 15:41:41 -07:00
parent 49aee79557
commit 9b5d8002a0
21 changed files with 316 additions and 183 deletions

View File

@ -1,4 +1,4 @@
const people = [ const userLites = [
{ {
uuid: "0", uuid: "0",
emailAddress: "cth0604@gmail.com", emailAddress: "cth0604@gmail.com",
@ -58,7 +58,7 @@ const meetings = [
meetingId: "1", meetingId: "1",
liveParticipantIds: [], liveParticipantIds: [],
registrantIds: ["0", "2", "4"], registrantIds: ["0", "2", "4"],
start: "2022-03-13T17:30:00", start: "2022-03-16T17:30:00",
duration: 30, duration: 30,
timezone: "", timezone: "",
joinUrl: "", joinUrl: "",
@ -66,7 +66,7 @@ const meetings = [
}, },
{ {
meetingId: "2", meetingId: "2",
liveParticipantIds: [], liveParticipantIds: ["3", "5"],
registrantIds: ["3", "5", "6"], registrantIds: ["3", "5", "6"],
start: "2022-03-13T17:30:00", start: "2022-03-13T17:30:00",
duration: 30, duration: 30,
@ -83,4 +83,6 @@ const team = {
directReports: [], directReports: [],
}; };
export { people, meetings, team }; const favorites = ["2", "4"];
export { userLites, meetings, team, favorites };

10
src/api-bodies/User.tsx Normal file
View File

@ -0,0 +1,10 @@
interface User {
uuid: string;
emailAddress: string;
name: string;
role: string;
inMeeting: boolean;
meetingID: string | null;
}
export default User;

View File

@ -0,0 +1,7 @@
interface UserStatus {
uuid: string;
inMeeting: boolean;
meetingID: string | null;
}
export default UserStatus;

View File

@ -16,10 +16,22 @@ const returnStatusColor = (
} }
}; };
const getMeetingDuration = (meeting: DetailedMeeting) => { const getUpcomingMeetingTime = (meeting: DetailedMeeting) => {
const startDate = new Date(meeting.start); const startDate = new Date(meeting.start);
const endDate = new Date(startDate.getTime() + meeting.duration * 60000); const endDate = new Date(startDate.getTime() + meeting.duration * 60000);
return `${startDate.toTimeString()} - ${endDate.toTimeString()}`; const startTime = startDate
.toTimeString()
.split(" ")[0]
.split(":")
.slice(0, 2)
.join(":");
const endTime = endDate
.toTimeString()
.split(" ")[0]
.split(":")
.slice(0, 2)
.join(":");
return `${startTime} - ${endTime}`;
}; };
export { returnStatusColor, getMeetingDuration }; export { returnStatusColor, getUpcomingMeetingTime };

View File

@ -16,6 +16,7 @@ const Body: React.FC<Props> = (props) => {
flexDirection: "column", flexDirection: "column",
width: "100%", width: "100%",
height: "100%", height: "100%",
mt: 2,
}} }}
> >
<Toolbar /> <Toolbar />

View File

@ -11,10 +11,7 @@ import React from "react";
import { ExpandLess, ExpandMore } from "@mui/icons-material"; import { ExpandLess, ExpandMore } from "@mui/icons-material";
import ContactItem from "./sidebar-components/ContactItem"; import ContactItem from "./sidebar-components/ContactItem";
import { useAppSelector } from "../../../redux/hooks"; import { useAppSelector } from "../../../redux/hooks";
import { import { selectUsers, selectTeam } from "../../../redux/slices/usersSlice";
selectFavoritesJSON,
selectTeamJSON,
} from "../../../redux/slices/peopleSlice";
import { selectFavorites } from "../../../redux/slices/favoritesSlice"; import { selectFavorites } from "../../../redux/slices/favoritesSlice";
import UserLite from "../../../api-bodies/UserLite"; import UserLite from "../../../api-bodies/UserLite";
@ -28,11 +25,11 @@ 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 favoritesUuids = useAppSelector(selectFavorites);
const favoritesJSON = useAppSelector((state) => const favorites = useAppSelector((state) =>
selectFavoritesJSON(state, favorites) selectUsers(state, favoritesUuids)
); );
const teamJSON = useAppSelector(selectTeamJSON); const team = useAppSelector(selectTeam);
return ( return (
<Drawer <Drawer
@ -54,13 +51,13 @@ const Sidebar: React.FC<Props> = (props) => {
{favoritesOpen ? <ExpandLess /> : <ExpandMore />} {favoritesOpen ? <ExpandLess /> : <ExpandMore />}
<ListItemText primary="Favorites" sx={{ textAlign: "center" }} /> <ListItemText primary="Favorites" sx={{ textAlign: "center" }} />
<ListItemText <ListItemText
primary={favoritesJSON.length} primary={favorites.length}
sx={{ textAlign: "right" }} sx={{ textAlign: "right" }}
/> />
</ListItemButton> </ListItemButton>
<Collapse in={favoritesOpen} timeout="auto" unmountOnExit> <Collapse in={favoritesOpen} timeout="auto" unmountOnExit>
<List disablePadding> <List disablePadding>
{favoritesJSON.map((favorite, i) => ( {favorites.map((favorite, i) => (
<ContactItem <ContactItem
contactInfo={favorite} contactInfo={favorite}
key={i} key={i}
@ -72,11 +69,11 @@ 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={teamJSON.length} sx={{ textAlign: "right" }} /> <ListItemText primary={team.length} sx={{ textAlign: "right" }} />
</ListItemButton> </ListItemButton>
<Collapse in={teamOpen} timeout="auto" unmountOnExit> <Collapse in={teamOpen} timeout="auto" unmountOnExit>
<List disablePadding> <List disablePadding>
{teamJSON.map((member, i) => ( {team.map((member, i) => (
<ContactItem <ContactItem
contactInfo={member} contactInfo={member}
key={i} key={i}

View File

@ -3,8 +3,8 @@ import React from "react";
import UserLite from "../../../../api-bodies/UserLite"; import UserLite from "../../../../api-bodies/UserLite";
import { useAppSelector, useAppDispatch } from "../../../../redux/hooks"; import { useAppSelector, useAppDispatch } from "../../../../redux/hooks";
import { open } from "../../../../redux/slices/meetingDetailsOpenSlice"; import { open } from "../../../../redux/slices/meetingDetailsOpenSlice";
import { selectUserUpcomingMeetings } from "../../../../redux/slices/meetingsSlice"; import { selectUserUpcomingMeetings } from "../../../../redux/slices/meetingsAndUserStatusSlice";
import { getMeetingDuration } from "../../Utils"; import { getUpcomingMeetingTime } from "../../Utils";
interface Props { interface Props {
contactInfo: UserLite; contactInfo: UserLite;
@ -53,7 +53,7 @@ const LowerBody: React.FC<Props> = (props) => {
{meeting.topic} {meeting.topic}
</Button> </Button>
<Typography sx={{ pt: 1.5 }}> <Typography sx={{ pt: 1.5 }}>
{getMeetingDuration(meeting)} {getUpcomingMeetingTime(meeting)}
</Typography> </Typography>
</Box> </Box>
))} ))}

View File

@ -6,12 +6,34 @@ import GroupsIcon from "@mui/icons-material/Groups";
import AddIcon from "@mui/icons-material/Add"; import AddIcon from "@mui/icons-material/Add";
import Status from "../../Status"; import Status from "../../Status";
import UserLite from "../../../../api-bodies/UserLite"; import UserLite from "../../../../api-bodies/UserLite";
import UserStatus from "../../../../api-bodies/UserStatus";
import { useAppSelector, useAppDispatch } from "../../../../redux/hooks";
import {
selectUserStatus,
selectMeeting,
} from "../../../../redux/slices/meetingsAndUserStatusSlice";
import {
selectFavorites,
addFavorite,
removeFavorite,
} from "../../../../redux/slices/favoritesSlice";
import RemoveIcon from "@mui/icons-material/Remove";
interface Props { interface Props {
contactInfo: UserLite; contactInfo: UserLite;
} }
const UpperBody: React.FC<Props> = (props) => { const UpperBody: React.FC<Props> = (props) => {
const dispatch = useAppDispatch();
const userStatus: UserStatus | null = useAppSelector((state) =>
selectUserStatus(state, props.contactInfo.uuid)
);
const favoritesUuids = useAppSelector(selectFavorites);
const detailedMeeting = useAppSelector((state) =>
selectMeeting(state, userStatus.meetingID)
);
const status: Status =
userStatus && userStatus.inMeeting ? Status.Online : Status.Offline;
return ( return (
<Box <Box
sx={{ sx={{
@ -34,9 +56,25 @@ const UpperBody: React.FC<Props> = (props) => {
}} }}
> >
<Typography variant="h3">{props.contactInfo.name}</Typography> <Typography variant="h3">{props.contactInfo.name}</Typography>
<Button variant="outlined" color="success" startIcon={<AddIcon />}> {!favoritesUuids.includes(props.contactInfo.uuid) ? (
favorites <Button
</Button> variant="outlined"
color="success"
startIcon={<AddIcon />}
onClick={() => dispatch(addFavorite(props.contactInfo.uuid))}
>
favorites
</Button>
) : (
<Button
variant="outlined"
color="secondary"
startIcon={<RemoveIcon />}
onClick={() => dispatch(removeFavorite(props.contactInfo.uuid))}
>
favorites
</Button>
)}
</Box> </Box>
<Box <Box
sx={{ sx={{
@ -64,8 +102,10 @@ 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" }}>{Status.Online}</Typography> <Typography sx={{ textAlign: "right" }}>{status}</Typography>
<Typography>MeetingName-1372</Typography> {detailedMeeting ? (
<Typography>{detailedMeeting.topic}</Typography>
) : null}
</Box> </Box>
</Box> </Box>
</Box> </Box>

View File

@ -5,6 +5,9 @@ import CircleIcon from "@mui/icons-material/Circle";
import { returnStatusColor } from "../../Utils"; import { returnStatusColor } from "../../Utils";
import UserLite from "../../../../api-bodies/UserLite"; import UserLite from "../../../../api-bodies/UserLite";
import Status from "../../Status"; import Status from "../../Status";
import { useAppSelector } from "../../../../redux/hooks";
import { selectUserStatus } from "../../../../redux/slices/meetingsAndUserStatusSlice";
import UserStatus from "../../../../api-bodies/UserStatus";
interface Props { interface Props {
contactInfo: UserLite; contactInfo: UserLite;
@ -12,6 +15,11 @@ interface Props {
} }
const ContactItem: React.FC<Props> = (props) => { const ContactItem: React.FC<Props> = (props) => {
const userStatus: UserStatus | null = useAppSelector((state) =>
selectUserStatus(state, props.contactInfo.uuid)
);
const status: Status =
userStatus && userStatus.inMeeting ? Status.Online : Status.Offline;
return ( return (
<ListItemButton <ListItemButton
onClick={() => { onClick={() => {
@ -23,10 +31,10 @@ const ContactItem: React.FC<Props> = (props) => {
</ListItemIcon> </ListItemIcon>
<ListItemText <ListItemText
primary={props.contactInfo.name} primary={props.contactInfo.name}
secondary={Status.Online} secondary={status}
sx={{ flexGrow: 1 }} sx={{ flexGrow: 1 }}
/> />
<CircleIcon color={returnStatusColor(Status.Online)} /> <CircleIcon color={returnStatusColor(status)} />
</ListItemButton> </ListItemButton>
); );
}; };

View File

@ -12,7 +12,7 @@ const MeetingDetails: React.FC = () => {
const meetingDetailsOpen = useAppSelector(selectMeetingDetailsOpen); const meetingDetailsOpen = useAppSelector(selectMeetingDetailsOpen);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
return ( return meetingDetailsOpen.meeting ? (
<Dialog <Dialog
fullScreen fullScreen
open={meetingDetailsOpen.open} open={meetingDetailsOpen.open}
@ -21,7 +21,7 @@ const MeetingDetails: React.FC = () => {
<Header meeting={meetingDetailsOpen.meeting} /> <Header meeting={meetingDetailsOpen.meeting} />
<Body meeting={meetingDetailsOpen.meeting} /> <Body meeting={meetingDetailsOpen.meeting} />
</Dialog> </Dialog>
); ) : null;
}; };
export default MeetingDetails; export default MeetingDetails;

View File

@ -0,0 +1,30 @@
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
const getMeetingStatus = (meeting: DetailedMeeting) => {
const startDate = new Date(meeting.start);
const endDate = new Date(startDate.getTime() + meeting.duration * 60000);
const currentDate = new Date();
if (currentDate > startDate && currentDate < endDate) return "Live";
else if (currentDate < startDate) return "Scheduled";
else return "Finished";
};
const getUpcomingMeetingTime = (meeting: DetailedMeeting) => {
const startDate = new Date(meeting.start);
const endDate = new Date(startDate.getTime() + meeting.duration * 60000);
const startTime = startDate
.toTimeString()
.split(" ")[0]
.split(":")
.slice(0, 2)
.join(":");
const endTime = endDate
.toTimeString()
.split(" ")[0]
.split(":")
.slice(0, 2)
.join(":");
return `${startTime} - ${endTime}`;
};
export { getMeetingStatus, getUpcomingMeetingTime };

View File

@ -9,12 +9,20 @@ import {
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"; import DetailedMeeting from "../../../api-bodies/DetailedMeeting";
import { useAppSelector } from "../../../redux/hooks";
import { selectUsers } from "../../../redux/slices/usersSlice";
import { getMeetingStatus } from "../Utils";
import UserLite from "../../../api-bodies/UserLite";
interface Props { interface Props {
meeting: DetailedMeeting | null; meeting: DetailedMeeting;
} }
const Body: React.FC<Props> = () => { const Body: React.FC<Props> = (props) => {
const registrants: UserLite[] = useAppSelector((state) =>
selectUsers(state, props.meeting.registrantIds)
);
return ( return (
<Box <Box
sx={{ sx={{
@ -34,7 +42,7 @@ const Body: React.FC<Props> = () => {
}} }}
> >
<Typography>Feb 10, 2022 10:45 am - 11:00 am</Typography> <Typography>Feb 10, 2022 10:45 am - 11:00 am</Typography>
<Typography>Status: Live</Typography> <Typography>Status: {getMeetingStatus(props.meeting)}</Typography>
<Typography> <Typography>
Topic: Lorem Ipsum is simply dummy text of the printing and Topic: Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the industrys standard typesetting industry. Lorem Ipsum has been the industrys standard
@ -56,20 +64,14 @@ const Body: React.FC<Props> = () => {
<ListItem sx={{ borderBottom: 1 }}> <ListItem sx={{ borderBottom: 1 }}>
<ListItemText primary="Invited" /> <ListItemText primary="Invited" />
</ListItem> </ListItem>
<ListItem> {registrants.map((registrant, i) => (
<ListItemIcon> <ListItem key={i}>
<PersonOutlineIcon /> <ListItemIcon>
</ListItemIcon> <PersonOutlineIcon />
<ListItemText primary="Taehee Choi" /> </ListItemIcon>
</ListItem> <ListItemText primary={registrant.name} />
</List> </ListItem>
<List> ))}
<ListItem>
<ListItemIcon>
<PersonOutlineIcon />
</ListItemIcon>
<ListItemText primary="Taehee Choi" />
</ListItem>
</List> </List>
</Box> </Box>
</Box> </Box>

View File

@ -5,14 +5,12 @@ import { AuthProvider } from "./context/AuthProvider";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { store } from "./redux/store"; import { store } from "./redux/store";
import { fetchFavorites } from "./redux/slices/favoritesSlice"; import { fetchFavorites } from "./redux/slices/favoritesSlice";
import { fetchTeam } from "./redux/slices/teamSlice"; import { fetchMeetings } from "./redux/slices/meetingsAndUserStatusSlice";
import { fetchMeetings } from "./redux/slices/meetingsSlice"; import { fetchUsers } from "./redux/slices/usersSlice";
import { fetchPeople } from "./redux/slices/peopleSlice";
store.dispatch(fetchPeople(""));
store.dispatch(fetchFavorites(""));
store.dispatch(fetchTeam(""));
store.dispatch(fetchMeetings("")); store.dispatch(fetchMeetings(""));
store.dispatch(fetchUsers(""));
store.dispatch(fetchFavorites(""));
const Index: React.FC = () => { const Index: React.FC = () => {
return ( return (

View File

@ -1,5 +1,6 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { RootState } from "../store"; import { RootState } from "../store";
import { favorites } from "../../api-bodies/MockData";
interface FavoritesState { interface FavoritesState {
favorites: string[]; favorites: string[];
@ -34,7 +35,7 @@ export const fetchFavorites = createAsyncThunk(
// const response = await client.post("/fakeApi/posts", initialPost); // const response = await client.post("/fakeApi/posts", initialPost);
// !!! // !!!
console.log(uuid); console.log(uuid);
return ["2", "4"]; return favorites;
} }
); );
export const addFavorite = createAsyncThunk( export const addFavorite = createAsyncThunk(

View File

@ -0,0 +1,78 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
import { RootState } from "../store";
import { meetings } from "../../api-bodies/MockData";
import UserStatus from "../../api-bodies/UserStatus";
interface MeetingsAndUserStatusState {
meetings: DetailedMeeting[];
userStatuses: Record<string, UserStatus>;
}
const initialState: MeetingsAndUserStatusState = {
meetings: [],
userStatuses: {},
};
export const meetingsAndUserStatusSlice = createSlice({
name: "meetingsAndUserStatus",
initialState,
reducers: {},
extraReducers(builder) {
builder.addCase(fetchMeetings.fulfilled, (state, action) => {
state.meetings = action.payload.meetings;
state.userStatuses = action.payload.userStatuses;
});
},
});
export const fetchMeetings = createAsyncThunk(
"meetingsAndUserStatus/fetchMeetings",
async (uuid: string) => {
// const response = await client.post("/fakeApi/posts", initialPost);
// !!!
console.log(uuid);
const userStatuses: Record<string, UserStatus> = {};
meetings.forEach((meeting) => {
meeting.liveParticipantIds.forEach((uuid) => {
userStatuses[uuid] = {
uuid: uuid,
inMeeting: true,
meetingID: meeting.meetingId,
};
});
});
return { userStatuses: userStatuses, meetings: meetings };
}
);
export const selectMeetings = (state: RootState) =>
state.meetingsAndUserStatuses.meetings;
export const selectMeeting = (state: RootState, meetingID: string | null) => {
return meetingID !== null
? state.meetingsAndUserStatuses.meetings.find(
(meeting) => meeting.meetingId === meetingID
)
: null;
};
export const selectUserUpcomingMeetings = (state: RootState, uuid: string) => {
return state.meetingsAndUserStatuses.meetings.filter((meeting) =>
meeting.registrantIds.includes(uuid)
);
};
export const selectUserStatus = (
state: RootState,
uuid: string
): UserStatus => {
const userStatus = state.meetingsAndUserStatuses.userStatuses[uuid];
if (userStatus) {
return userStatus;
} else {
return {
uuid: uuid,
inMeeting: false,
meetingID: null,
};
}
};
export default meetingsAndUserStatusSlice.reducer;

View File

@ -1,41 +0,0 @@
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;

View File

@ -1,40 +0,0 @@
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;

View File

@ -1,41 +0,0 @@
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;

View File

@ -0,0 +1,66 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { RootState } from "../store";
import { userLites, team } from "../../api-bodies/MockData";
import UserLite from "../../api-bodies/UserLite";
interface TeamState {
user: string | null;
manager: string | null;
sameManager: string[];
directReports: string[];
}
interface UsersState {
users: Record<string, UserLite>;
team: TeamState;
}
const initialState: UsersState = {
users: {},
team: { user: null, manager: null, sameManager: [], directReports: [] },
};
export const usersSlice = createSlice({
name: "users",
initialState,
reducers: {},
extraReducers(builder) {
builder.addCase(fetchUsers.fulfilled, (state, action) => {
state.users = action.payload.users;
state.team = action.payload.team;
});
},
});
export const fetchUsers = createAsyncThunk(
"users/fetchUsers",
async (uuid: string) => {
// fetch userfull
// fetch managerfull
// now you have yourself, co-workers, manager, and direct reports (your team basically!)
// call setTeam reducer in teamSlice
console.log(uuid);
const users: Record<string, UserLite> = {};
userLites.forEach((userLite) => {
users[userLite.uuid] = userLite;
});
return { users: users, team: team };
}
);
export const selectUsers = (state: RootState, uuids: string[]): UserLite[] => {
const users: UserLite[] = [];
uuids.forEach((uuid) => users.push(state.users.users[uuid]));
return users;
};
export const selectTeam = (state: RootState) => {
const team: UserLite[] = [];
if (state.users.team.manager !== null)
team.push(state.users.users[state.users.team.manager]);
state.users.team.sameManager.forEach((u) => team.push(state.users.users[u]));
state.users.team.directReports.forEach((u) =>
team.push(state.users.users[u])
);
return team;
};
export default usersSlice.reducer;

View File

@ -1,17 +1,15 @@
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import meetingDetailsOpenReducer from "./slices/meetingDetailsOpenSlice"; import meetingDetailsOpenReducer from "./slices/meetingDetailsOpenSlice";
import favoritesReducer from "./slices/favoritesSlice"; import favoritesReducer from "./slices/favoritesSlice";
import teamReducer from "./slices/teamSlice"; import meetingsAndUserStatusReducer from "./slices/meetingsAndUserStatusSlice";
import meetingsReducer from "./slices/meetingsSlice"; import usersReducer from "./slices/usersSlice";
import peopleReducer from "./slices/peopleSlice";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
meetingDetailsOpen: meetingDetailsOpenReducer, meetingDetailsOpen: meetingDetailsOpenReducer,
favorites: favoritesReducer, favorites: favoritesReducer,
team: teamReducer, meetingsAndUserStatuses: meetingsAndUserStatusReducer,
meetings: meetingsReducer, users: usersReducer,
people: peopleReducer,
}, },
}); });

View File

@ -5,3 +5,8 @@ body,
#app > div { #app > div {
height: 100%; height: 100%;
} }
html,
body {
overflow: hidden;
}