Files
Checkmate/Client/src/Components/Sidebar/index.jsx
T

216 lines
6.5 KiB
React
Raw Normal View History

import { useState } from "react";
import { Menu, MenuItem, Stack, Tooltip, Typography } from "@mui/material";
2024-07-26 12:39:18 -04:00
import { useLocation, useNavigate } from "react-router";
import { useTheme } from "@emotion/react";
import { useDispatch, useSelector } from "react-redux";
import { clearAuthState } from "../../Features/Auth/authSlice";
import { clearUptimeMonitorState } from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { createToast } from "../../Utils/toastUtils";
import axiosInstance from "../../Utils/axiosConfig";
import Avatar from "../Avatar";
import LockSvg from "../../assets/icons/lock.svg?react";
import UserSvg from "../../assets/icons/user.svg?react";
import TeamSvg from "../../assets/icons/user-two.svg?react";
import LogoutSvg from "../../assets/icons/logout.svg?react";
2024-07-26 12:39:18 -04:00
import BWULogo from "../../assets/Images/bwl-logo.svg?react";
import Support from "../../assets/icons/support.svg?react";
import StatusPages from "../../assets/icons/status-pages.svg?react";
import Maintenance from "../../assets/icons/maintenance.svg?react";
import Monitors from "../../assets/icons/monitors.svg?react";
import Incidents from "../../assets/icons/incidents.svg?react";
import Integrations from "../../assets/icons/integrations.svg?react";
import PageSpeed from "../../assets/icons/page-speed.svg?react";
import Settings from "../../assets/icons/settings.svg?react";
import Arrow from "../../assets/icons/down-arrow.svg?react";
2024-07-26 12:39:18 -04:00
import "./index.css";
const menu = [
{ name: "Monitors", path: "monitors", icon: <Monitors /> },
{ name: "Incidents", path: "incidents", icon: <Incidents /> },
{ name: "Status pages", path: "status", icon: <StatusPages /> },
{ name: "Maintenance", path: "maintenance", icon: <Maintenance /> },
2024-08-02 18:08:36 -04:00
{ name: "Page speed", path: "pagespeed", icon: <PageSpeed /> },
2024-07-28 16:51:47 -04:00
{ name: "Integrations", path: "integrations", icon: <Integrations /> },
2024-07-26 12:39:18 -04:00
{ name: "Support", path: "support", icon: <Support /> },
{ name: "Settings", path: "settings", icon: <Settings /> },
];
const icons = {
Profile: <UserSvg />,
Team: <TeamSvg />,
Password: <LockSvg />,
Logout: <LogoutSvg />,
};
/**
* @component
* Sidebar component serves as a sidebar containing a menu.
*
* @returns {JSX.Element} The JSX element representing the Sidebar component.
*/
2024-07-26 12:39:18 -04:00
function Sidebar() {
const theme = useTheme();
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
const [anchorElUser, setAnchorElUser] = useState(null);
const authState = useSelector((state) => state.auth);
// Initialize settings and update based on user role
let settings = ["Profile", "Password", "Team", "Logout"];
if (authState.user?.role && !authState.user.role.includes("admin")) {
settings = ["Profile", "Password", "Logout"];
}
/**
* Handles opening the user menu.
*
* @param {React.MouseEvent<HTMLElement>} event - The event triggered by clicking the user menu button.
*/
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
/**
* Handles logging out the user
*
*/
const logout = async () => {
try {
// Make request to BE to remove JWT from user
await axiosInstance.post(
"/auth/logout",
{ email: authState.user.email },
{
headers: {
Authorization: `Bearer ${authState.authToken}`,
"Content-Type": "application/json",
},
}
);
// Clear auth state
dispatch(clearAuthState());
dispatch(clearUptimeMonitorState());
navigate("/login");
} catch (error) {
createToast({
body: error.message,
});
}
};
/**
* Handles closing the user menu.
*/
const handleCloseUserMenu = (setting) => {
setAnchorElUser(null);
switch (setting) {
case "Profile":
navigate("/account/profile");
break;
case "Team":
navigate("/account/team");
break;
case "Password":
navigate("/account/password");
break;
case "Logout":
logout();
break;
default:
break;
}
};
2024-07-26 12:39:18 -04:00
return (
<Stack component="aside" gap={theme.gap.xs}>
<BWULogo alt="BlueWave Uptime Logo" />
{menu.map((item) => (
<Stack
className={
location.pathname.includes(item.path) ? "selected-path" : ""
}
key={item.path}
direction="row"
alignItems="center"
py={theme.gap.small}
px={theme.gap.medium}
2024-07-26 12:39:18 -04:00
gap={theme.gap.small}
borderRadius={`${theme.shape.borderRadius}px`}
2024-08-02 17:47:22 -04:00
onClick={() =>
item.path === "support"
? window.open(
"https://github.com/bluewave-labs/bluewave-uptime",
"_blank",
"noreferrer"
)
: navigate(`/${item.path}`)
}
2024-07-26 12:39:18 -04:00
>
{item.icon}
<Typography component="span">{item.name}</Typography>
</Stack>
))}
<Tooltip
title="Open settings"
slotProps={{
popper: {
modifiers: [
{
name: "offset",
options: {
offset: [0, -14],
},
},
],
},
}}
>
<Stack
direction="row"
alignItems="center"
py={theme.gap.small}
px={theme.gap.medium}
gap={theme.gap.xs}
borderRadius={`${theme.shape.borderRadius}px`}
onClick={handleOpenUserMenu}
>
<Avatar small={true} />
<Typography component="span" ml={theme.gap.xs}>
{authState.user?.firstName} {authState.user?.lastName}
</Typography>
<Arrow style={{ marginTop: "2px", marginLeft: "auto" }} />
</Stack>
</Tooltip>
<Menu
className="sidebar-menu"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: "top",
horizontal: "center",
}}
keepMounted
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
autoFocus={false}
sx={{
ml: theme.gap.xxl,
}}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={() => handleCloseUserMenu(setting)}>
{icons[setting]}
<Typography component="span" ml={theme.gap.small}>
{setting}
</Typography>
</MenuItem>
))}
</Menu>
2024-07-26 12:39:18 -04:00
</Stack>
);
}
export default Sidebar;