Merge pull request #3 from CPSC319-Winter-term-2/mbalsdon-sidebar
Non-functional sidebar components
This commit is contained in:
commit
d4c3ca4a5a
31
src/App.tsx
31
src/App.tsx
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useState } 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";
|
||||||
|
|
||||||
@ -11,10 +11,39 @@ import { ThemeProvider } from "@emotion/react";
|
|||||||
import Theme from "./Theme";
|
import Theme from "./Theme";
|
||||||
|
|
||||||
import "./style/App.css";
|
import "./style/App.css";
|
||||||
|
import Sidebar from "./components/sidebar/Sidebar";
|
||||||
|
import { MeetingStatus, SidebarUserObj } from "./components/sidebar/SidebarUser";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
||||||
|
/* Temporary data */
|
||||||
|
const [sidebarUsers] = 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 },
|
||||||
|
{ id: 4, name: "Bob B.", meetingStatus: MeetingStatus.IN_MEETING },
|
||||||
|
{ id: 5, name: "Bob C.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 6, name: "Bob D.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
|
{ id: 7, name: "Bob E.", meetingStatus: MeetingStatus.AWAY },
|
||||||
|
{ id: 8, name: "Bob F.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 9, name: "Bob G.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
|
{ id: 10, name: "Bob H.", meetingStatus: MeetingStatus.AWAY },
|
||||||
|
{ id: 11, name: "Bob I.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 12, name: "Bob J.", meetingStatus: MeetingStatus.AWAY },
|
||||||
|
{ id: 13, name: "Bob K.", meetingStatus: MeetingStatus.IN_MEETING },
|
||||||
|
{ id: 14, name: "Bob L.", meetingStatus: MeetingStatus.IN_MEETING },
|
||||||
|
{ id: 15, name: "Bob M.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 16, name: "Bob N.", meetingStatus: MeetingStatus.OFFLINE },
|
||||||
|
{ id: 17, name: "Bob O.", meetingStatus: MeetingStatus.AWAY },
|
||||||
|
{ id: 18, name: "Bob P.", meetingStatus: MeetingStatus.AWAY },
|
||||||
|
{ id: 19, name: "Bob Q.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
|
{ id: 20, name: "Bob R.", meetingStatus: MeetingStatus.ONLINE },
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={Theme}>
|
<ThemeProvider theme={Theme}>
|
||||||
|
<Sidebar users={sidebarUsers} />
|
||||||
<Router>
|
<Router>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<Routes>
|
<Routes>
|
||||||
|
|||||||
40
src/components/sidebar/GroupSelect.tsx
Normal file
40
src/components/sidebar/GroupSelect.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent, Typography } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
// TODO: change MenuItem values to something meaningful
|
||||||
|
|
||||||
|
const GroupSelect: React.FC = () => {
|
||||||
|
|
||||||
|
const [group, setGroup] = useState("");
|
||||||
|
|
||||||
|
const handleChange = (event: SelectChangeEvent) => {
|
||||||
|
setGroup(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl variant="filled" fullWidth>
|
||||||
|
<InputLabel id="group-select-label">
|
||||||
|
<Typography color="black">Group</Typography>
|
||||||
|
</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="group-select-label"
|
||||||
|
id="group-select"
|
||||||
|
value={group}
|
||||||
|
label="Group"
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>
|
||||||
|
<Typography color="black">Favourites</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem value={1}>
|
||||||
|
<Typography color="black">Contacts</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem value={2}>
|
||||||
|
<Typography color="black">Office</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GroupSelect;
|
||||||
44
src/components/sidebar/SettingsButton.tsx
Normal file
44
src/components/sidebar/SettingsButton.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { Settings } from "@mui/icons-material";
|
||||||
|
import { IconButton, Menu, MenuItem } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const SettingsButton: React.FC = () => {
|
||||||
|
|
||||||
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
|
const open = Boolean(anchorEl);
|
||||||
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
};
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<IconButton
|
||||||
|
sx={{ position: "absolute", right: 0 }}
|
||||||
|
aria-controls={open ? "context-menu" : undefined}
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded={open ? "true" : undefined}
|
||||||
|
onClick={handleClick}>
|
||||||
|
<Settings />
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id="context-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
MenuListProps={{ "aria-labelledby": "basic-button" }}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={handleClose}>Remove from Favourites</MenuItem>
|
||||||
|
<MenuItem onClick={handleClose}>View current meeting</MenuItem>
|
||||||
|
<MenuItem onClick={handleClose}>View upcoming meetings</MenuItem>
|
||||||
|
<MenuItem onClick={handleClose}>Create meeting</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingsButton;
|
||||||
@ -1,5 +1,42 @@
|
|||||||
const Sidebar: React.FC = () => {
|
import { Divider, Drawer, List, ListItem, ListSubheader } from "@mui/material";
|
||||||
return <span>Sidebar</span>;
|
import GroupSelect from "./GroupSelect";
|
||||||
|
import SidebarUser, { SidebarUserObj } from "./SidebarUser";
|
||||||
|
|
||||||
|
// TODO: toolbar on top of sidebar since it goes under the navbar
|
||||||
|
|
||||||
|
const drawerWidth = 240;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
users: SidebarUserObj[],
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sidebar: React.FC<Props> = ({ users }: Props) => {
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
sx={{
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
"& .MuiDrawer-paper": {
|
||||||
|
width: drawerWidth,
|
||||||
|
boxSizing: "border-box",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
variant="permanent"
|
||||||
|
anchor="right"
|
||||||
|
>
|
||||||
|
<List disablePadding sx={{ height: "80%", overflow: "auto" }}>
|
||||||
|
<ListSubheader disableGutters>
|
||||||
|
<GroupSelect />
|
||||||
|
</ListSubheader>
|
||||||
|
{users.map((user) => (
|
||||||
|
<ListItem disablePadding key={user.id}>
|
||||||
|
<SidebarUser user={user} />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Divider />
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Sidebar;
|
export default Sidebar;
|
||||||
70
src/components/sidebar/SidebarUser.tsx
Normal file
70
src/components/sidebar/SidebarUser.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { Box, Typography } from "@mui/material";
|
||||||
|
import SettingsButton from "./SettingsButton";
|
||||||
|
|
||||||
|
export interface SidebarUserObj {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
meetingStatus: MeetingStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum MeetingStatus {
|
||||||
|
OFFLINE = 0,
|
||||||
|
ONLINE = 1,
|
||||||
|
AWAY = 2,
|
||||||
|
IN_MEETING = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMeetingStatusText = (ms: MeetingStatus): string => {
|
||||||
|
switch (ms) {
|
||||||
|
case MeetingStatus.OFFLINE: {
|
||||||
|
return "Offline";
|
||||||
|
}
|
||||||
|
case MeetingStatus.ONLINE: {
|
||||||
|
return "Online";
|
||||||
|
}
|
||||||
|
case MeetingStatus.AWAY: {
|
||||||
|
return "Away";
|
||||||
|
}
|
||||||
|
case MeetingStatus.IN_MEETING: {
|
||||||
|
return "In meeting";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusColor = (ms: MeetingStatus): string => {
|
||||||
|
switch (ms) {
|
||||||
|
case MeetingStatus.OFFLINE: {
|
||||||
|
return "#b8b8b8";
|
||||||
|
}
|
||||||
|
case MeetingStatus.ONLINE: {
|
||||||
|
return "#70ff70";
|
||||||
|
}
|
||||||
|
case MeetingStatus.AWAY: {
|
||||||
|
return "#ff7070";
|
||||||
|
}
|
||||||
|
case MeetingStatus.IN_MEETING: {
|
||||||
|
return "#e8da46";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
user: SidebarUserObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SidebarUser: React.FC<Props> = ({ user }: Props) => {
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "row", p: 1 }}>
|
||||||
|
<Box
|
||||||
|
bgcolor={getStatusColor(user.meetingStatus)}
|
||||||
|
sx={{ p: 1 }} />
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "column", ml: 1 }}>
|
||||||
|
<Typography variant="h6">{user.name}</Typography>
|
||||||
|
<Typography variant="caption">{getMeetingStatusText(user.meetingStatus)}</Typography>
|
||||||
|
</Box>
|
||||||
|
<SettingsButton />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SidebarUser;
|
||||||
Reference in New Issue
Block a user