Merge pull request #31 from CPSC319-Winter-term-2/front-end-fixes
redux updates
This commit is contained in:
commit
16587686d4
@ -1,4 +1,4 @@
|
||||
const people = [
|
||||
const userLites = [
|
||||
{
|
||||
uuid: "0",
|
||||
emailAddress: "cth0604@gmail.com",
|
||||
@ -58,7 +58,7 @@ const meetings = [
|
||||
meetingId: "1",
|
||||
liveParticipantIds: [],
|
||||
registrantIds: ["0", "2", "4"],
|
||||
start: "2022-03-13T17:30:00",
|
||||
start: "2022-03-16T17:30:00",
|
||||
duration: 30,
|
||||
timezone: "",
|
||||
joinUrl: "",
|
||||
@ -66,7 +66,7 @@ const meetings = [
|
||||
},
|
||||
{
|
||||
meetingId: "2",
|
||||
liveParticipantIds: [],
|
||||
liveParticipantIds: ["3", "5"],
|
||||
registrantIds: ["3", "5", "6"],
|
||||
start: "2022-03-13T17:30:00",
|
||||
duration: 30,
|
||||
@ -83,4 +83,6 @@ const team = {
|
||||
directReports: [],
|
||||
};
|
||||
|
||||
export { people, meetings, team };
|
||||
const favorites = ["2", "4"];
|
||||
|
||||
export { userLites, meetings, team, favorites };
|
||||
|
||||
10
src/api-bodies/User.tsx
Normal file
10
src/api-bodies/User.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
interface User {
|
||||
uuid: string;
|
||||
emailAddress: string;
|
||||
name: string;
|
||||
role: string;
|
||||
inMeeting: boolean;
|
||||
meetingID: string | null;
|
||||
}
|
||||
|
||||
export default User;
|
||||
7
src/api-bodies/UserStatus.tsx
Normal file
7
src/api-bodies/UserStatus.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
interface UserStatus {
|
||||
uuid: string;
|
||||
inMeeting: boolean;
|
||||
meetingID: string | null;
|
||||
}
|
||||
|
||||
export default UserStatus;
|
||||
@ -16,10 +16,22 @@ const returnStatusColor = (
|
||||
}
|
||||
};
|
||||
|
||||
const getMeetingDuration = (meeting: DetailedMeeting) => {
|
||||
const getUpcomingMeetingTime = (meeting: DetailedMeeting) => {
|
||||
const startDate = new Date(meeting.start);
|
||||
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 };
|
||||
|
||||
@ -16,6 +16,7 @@ const Body: React.FC<Props> = (props) => {
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
mt: 2,
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
|
||||
@ -11,10 +11,7 @@ import React from "react";
|
||||
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||
import ContactItem from "./sidebar-components/ContactItem";
|
||||
import { useAppSelector } from "../../../redux/hooks";
|
||||
import {
|
||||
selectFavoritesJSON,
|
||||
selectTeamJSON,
|
||||
} from "../../../redux/slices/peopleSlice";
|
||||
import { selectUsers, selectTeam } from "../../../redux/slices/usersSlice";
|
||||
import { selectFavorites } from "../../../redux/slices/favoritesSlice";
|
||||
import UserLite from "../../../api-bodies/UserLite";
|
||||
|
||||
@ -28,11 +25,11 @@ const Sidebar: React.FC<Props> = (props) => {
|
||||
const [favoritesOpen, setFavoritesOpen] = React.useState<boolean>(true);
|
||||
const [teamOpen, setTeamOpen] = React.useState<boolean>(false);
|
||||
|
||||
const favorites = useAppSelector(selectFavorites);
|
||||
const favoritesJSON = useAppSelector((state) =>
|
||||
selectFavoritesJSON(state, favorites)
|
||||
const favoritesUuids = useAppSelector(selectFavorites);
|
||||
const favorites = useAppSelector((state) =>
|
||||
selectUsers(state, favoritesUuids)
|
||||
);
|
||||
const teamJSON = useAppSelector(selectTeamJSON);
|
||||
const team = useAppSelector(selectTeam);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
@ -54,13 +51,13 @@ const Sidebar: React.FC<Props> = (props) => {
|
||||
{favoritesOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
<ListItemText primary="Favorites" sx={{ textAlign: "center" }} />
|
||||
<ListItemText
|
||||
primary={favoritesJSON.length}
|
||||
primary={favorites.length}
|
||||
sx={{ textAlign: "right" }}
|
||||
/>
|
||||
</ListItemButton>
|
||||
<Collapse in={favoritesOpen} timeout="auto" unmountOnExit>
|
||||
<List disablePadding>
|
||||
{favoritesJSON.map((favorite, i) => (
|
||||
{favorites.map((favorite, i) => (
|
||||
<ContactItem
|
||||
contactInfo={favorite}
|
||||
key={i}
|
||||
@ -72,11 +69,11 @@ const Sidebar: React.FC<Props> = (props) => {
|
||||
<ListItemButton onClick={() => setTeamOpen(!teamOpen)}>
|
||||
{teamOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
<ListItemText primary="Team" sx={{ textAlign: "center" }} />
|
||||
<ListItemText primary={teamJSON.length} sx={{ textAlign: "right" }} />
|
||||
<ListItemText primary={team.length} sx={{ textAlign: "right" }} />
|
||||
</ListItemButton>
|
||||
<Collapse in={teamOpen} timeout="auto" unmountOnExit>
|
||||
<List disablePadding>
|
||||
{teamJSON.map((member, i) => (
|
||||
{team.map((member, i) => (
|
||||
<ContactItem
|
||||
contactInfo={member}
|
||||
key={i}
|
||||
|
||||
@ -3,8 +3,8 @@ import React from "react";
|
||||
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";
|
||||
import { selectUserUpcomingMeetings } from "../../../../redux/slices/meetingsAndUserStatusSlice";
|
||||
import { getUpcomingMeetingTime } from "../../Utils";
|
||||
|
||||
interface Props {
|
||||
contactInfo: UserLite;
|
||||
@ -53,7 +53,7 @@ const LowerBody: React.FC<Props> = (props) => {
|
||||
{meeting.topic}
|
||||
</Button>
|
||||
<Typography sx={{ pt: 1.5 }}>
|
||||
{getMeetingDuration(meeting)}
|
||||
{getUpcomingMeetingTime(meeting)}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
|
||||
@ -6,12 +6,34 @@ import GroupsIcon from "@mui/icons-material/Groups";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import Status from "../../Status";
|
||||
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 {
|
||||
contactInfo: UserLite;
|
||||
}
|
||||
|
||||
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 (
|
||||
<Box
|
||||
sx={{
|
||||
@ -34,9 +56,25 @@ const UpperBody: React.FC<Props> = (props) => {
|
||||
}}
|
||||
>
|
||||
<Typography variant="h3">{props.contactInfo.name}</Typography>
|
||||
<Button variant="outlined" color="success" startIcon={<AddIcon />}>
|
||||
favorites
|
||||
</Button>
|
||||
{!favoritesUuids.includes(props.contactInfo.uuid) ? (
|
||||
<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
|
||||
sx={{
|
||||
@ -64,8 +102,10 @@ const UpperBody: React.FC<Props> = (props) => {
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||
<Typography sx={{ textAlign: "right" }}>{Status.Online}</Typography>
|
||||
<Typography>MeetingName-1372</Typography>
|
||||
<Typography sx={{ textAlign: "right" }}>{status}</Typography>
|
||||
{detailedMeeting ? (
|
||||
<Typography>{detailedMeeting.topic}</Typography>
|
||||
) : null}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@ -5,6 +5,9 @@ import CircleIcon from "@mui/icons-material/Circle";
|
||||
import { returnStatusColor } from "../../Utils";
|
||||
import UserLite from "../../../../api-bodies/UserLite";
|
||||
import Status from "../../Status";
|
||||
import { useAppSelector } from "../../../../redux/hooks";
|
||||
import { selectUserStatus } from "../../../../redux/slices/meetingsAndUserStatusSlice";
|
||||
import UserStatus from "../../../../api-bodies/UserStatus";
|
||||
|
||||
interface Props {
|
||||
contactInfo: UserLite;
|
||||
@ -12,6 +15,11 @@ interface 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 (
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
@ -23,10 +31,10 @@ const ContactItem: React.FC<Props> = (props) => {
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={props.contactInfo.name}
|
||||
secondary={Status.Online}
|
||||
secondary={status}
|
||||
sx={{ flexGrow: 1 }}
|
||||
/>
|
||||
<CircleIcon color={returnStatusColor(Status.Online)} />
|
||||
<CircleIcon color={returnStatusColor(status)} />
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
||||
|
||||
@ -12,7 +12,7 @@ const MeetingDetails: React.FC = () => {
|
||||
const meetingDetailsOpen = useAppSelector(selectMeetingDetailsOpen);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
return (
|
||||
return meetingDetailsOpen.meeting ? (
|
||||
<Dialog
|
||||
fullScreen
|
||||
open={meetingDetailsOpen.open}
|
||||
@ -21,7 +21,7 @@ const MeetingDetails: React.FC = () => {
|
||||
<Header meeting={meetingDetailsOpen.meeting} />
|
||||
<Body meeting={meetingDetailsOpen.meeting} />
|
||||
</Dialog>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default MeetingDetails;
|
||||
|
||||
30
src/components/meeting-details/Utils.tsx
Normal file
30
src/components/meeting-details/Utils.tsx
Normal 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 };
|
||||
@ -9,12 +9,20 @@ import {
|
||||
import React from "react";
|
||||
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
||||
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 {
|
||||
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 (
|
||||
<Box
|
||||
sx={{
|
||||
@ -34,7 +42,7 @@ const Body: React.FC<Props> = () => {
|
||||
}}
|
||||
>
|
||||
<Typography>Feb 10, 2022 10:45 am - 11:00 am</Typography>
|
||||
<Typography>Status: Live</Typography>
|
||||
<Typography>Status: {getMeetingStatus(props.meeting)}</Typography>
|
||||
<Typography>
|
||||
Topic: Lorem Ipsum is simply dummy text of the printing and
|
||||
typesetting industry. Lorem Ipsum has been the industrys standard
|
||||
@ -56,20 +64,14 @@ const Body: React.FC<Props> = () => {
|
||||
<ListItem sx={{ borderBottom: 1 }}>
|
||||
<ListItemText primary="Invited" />
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PersonOutlineIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Taehee Choi" />
|
||||
</ListItem>
|
||||
</List>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PersonOutlineIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Taehee Choi" />
|
||||
</ListItem>
|
||||
{registrants.map((registrant, i) => (
|
||||
<ListItem key={i}>
|
||||
<ListItemIcon>
|
||||
<PersonOutlineIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={registrant.name} />
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@ -5,14 +5,12 @@ 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";
|
||||
import { fetchMeetings } from "./redux/slices/meetingsAndUserStatusSlice";
|
||||
import { fetchUsers } from "./redux/slices/usersSlice";
|
||||
|
||||
store.dispatch(fetchPeople(""));
|
||||
store.dispatch(fetchFavorites(""));
|
||||
store.dispatch(fetchTeam(""));
|
||||
store.dispatch(fetchMeetings(""));
|
||||
store.dispatch(fetchUsers(""));
|
||||
store.dispatch(fetchFavorites(""));
|
||||
|
||||
const Index: React.FC = () => {
|
||||
return (
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||
import { RootState } from "../store";
|
||||
import { favorites } from "../../api-bodies/MockData";
|
||||
|
||||
interface FavoritesState {
|
||||
favorites: string[];
|
||||
@ -34,7 +35,7 @@ export const fetchFavorites = createAsyncThunk(
|
||||
// const response = await client.post("/fakeApi/posts", initialPost);
|
||||
// !!!
|
||||
console.log(uuid);
|
||||
return ["2", "4"];
|
||||
return favorites;
|
||||
}
|
||||
);
|
||||
export const addFavorite = createAsyncThunk(
|
||||
|
||||
78
src/redux/slices/meetingsAndUserStatusSlice.tsx
Normal file
78
src/redux/slices/meetingsAndUserStatusSlice.tsx
Normal 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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
66
src/redux/slices/usersSlice.tsx
Normal file
66
src/redux/slices/usersSlice.tsx
Normal 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;
|
||||
@ -1,17 +1,15 @@
|
||||
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";
|
||||
import meetingsAndUserStatusReducer from "./slices/meetingsAndUserStatusSlice";
|
||||
import usersReducer from "./slices/usersSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
meetingDetailsOpen: meetingDetailsOpenReducer,
|
||||
favorites: favoritesReducer,
|
||||
team: teamReducer,
|
||||
meetings: meetingsReducer,
|
||||
people: peopleReducer,
|
||||
meetingsAndUserStatuses: meetingsAndUserStatusReducer,
|
||||
users: usersReducer,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -5,3 +5,8 @@ body,
|
||||
#app > div {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user