diff --git a/Client/src/Components/Sidebar/index.css b/Client/src/Components/Sidebar/index.css index 4840043c3..63c365742 100644 --- a/Client/src/Components/Sidebar/index.css +++ b/Client/src/Components/Sidebar/index.css @@ -1,68 +1,79 @@ -aside .MuiStack-root { - cursor: pointer; -} -aside > svg { - margin: var(--env-var-spacing-2) var(--env-var-spacing-1); -} aside .selected-path, -aside .MuiStack-root:hover { +aside .MuiListItemButton-root:hover { background-color: var(--env-var-color-13); } -aside .MuiStack-root svg { +aside .MuiList-root svg { width: 20px; height: 20px; - opacity: 0.8; + opacity: 0.9; +} +aside .MuiList-root svg path { + stroke: var(--env-var-color-2); } aside span.MuiTypography-root { font-size: var(--env-var-font-size-medium); - color: var(--env-var-color-5); line-height: 1; } -aside .MuiStack-root:nth-last-child(3) { - margin-top: auto; +aside .MuiListSubheader-root { + font-size: var(--env-var-font-size-small); + font-weight: 500; + line-height: 1.5; + text-transform: uppercase; + margin-bottom: 2px; + opacity: 0.6; } -aside .MuiStack-root:last-child, -aside .MuiStack-root:nth-last-child(3) { +aside span.MuiTypography-root, +aside p.MuiTypography-root, +aside .MuiListSubheader-root { + color: var(--env-var-color-5); +} +aside p.MuiTypography-root { + font-size: var(--env-var-font-size-small); + opacity: 0.8; +} +aside .MuiListItemButton-root:not(.selected-path) > * { + opacity: 0.9; +} +aside .selected-path > * { + opacity: 1; +} +aside .selected-path span.MuiTypography-root { + font-weight: 600; +} +aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root { position: relative; } -aside .MuiStack-root:last-child:before { +aside .MuiDivider-root { + border-color: var(--env-var-color-6); +} +aside + .MuiCollapse-wrapperInner + .MuiList-root + > .MuiListItemButton-root::before { content: ""; position: absolute; - top: -10px; - left: 0; + left: -8px; + top: 0; + height: 100%; width: 100%; - border-top: solid 1px var(--env-var-color-6); + border-left: solid 1px var(--env-var-color-5); + opacity: 0.3; } -aside .MuiStack-root:last-child { - margin-top: 15px; +aside + .MuiCollapse-wrapperInner + .MuiList-root + > .MuiListItemButton-root:last-child::before { + height: 50%; } -.sidebar-menu { - margin-top: -20px; -} -.sidebar-menu .MuiPaper-root { - box-shadow: var(--env-var-shadow-1); - border: solid 1px var(--env-var-color-6); - border-radius: var(--env-var-radius-1); - gap: 1px; -} -.sidebar-menu .MuiList-root { - min-width: 100px; - width: 150px; - padding-bottom: 0; -} -.sidebar-menu li.MuiButtonBase-root:last-child { - border-top: solid 1px var(--env-var-color-6); - padding: 12px 16px; -} -.sidebar-menu li.MuiButtonBase-root { - min-height: fit-content; -} -.sidebar-menu .MuiList-root svg { - width: 16px; - height: 16px; -} -.sidebar-menu span { - font-size: var(--env-var-font-size-medium); - color: var(--env-var-color-2); +aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root::after { + content: ""; + position: absolute; + left: -8px; + top: 50%; + height: 1px; + width: 7px; + border-radius: 50%; + background-color: var(--env-var-color-5); + opacity: 0.3; } diff --git a/Client/src/Components/Sidebar/index.jsx b/Client/src/Components/Sidebar/index.jsx index 33ccdafc9..1ab2171cb 100644 --- a/Client/src/Components/Sidebar/index.jsx +++ b/Client/src/Components/Sidebar/index.jsx @@ -1,12 +1,23 @@ -import { useState } from "react"; -import { Menu, MenuItem, Stack, Tooltip, Typography } from "@mui/material"; +import React, { useEffect, useState } from "react"; +import { + Box, + Collapse, + Divider, + IconButton, + List, + ListItemButton, + ListItemIcon, + ListItemText, + ListSubheader, + Stack, + Tooltip, + Typography, +} from "@mui/material"; 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"; @@ -14,6 +25,8 @@ import TeamSvg from "../../assets/icons/user-two.svg?react"; import LogoutSvg from "../../assets/icons/logout.svg?react"; import BWULogo from "../../assets/Images/bwl-logo.svg?react"; import Support from "../../assets/icons/support.svg?react"; +import Dashboard from "../../assets/icons/dashboard.svg?react"; +import Account from "../../assets/icons/user-edit.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"; @@ -21,28 +34,40 @@ 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"; +import ArrowDown from "../../assets/icons/down-arrow.svg?react"; +import ArrowUp from "../../assets/icons/up-arrow.svg?react"; import "./index.css"; const menu = [ - { name: "Monitors", path: "monitors", icon: }, + { + name: "Dashboard", + icon: , + nested: [ + { name: "Monitors", path: "monitors", icon: }, + { name: "Pagespeed", path: "pagespeed", icon: }, + ], + }, { name: "Incidents", path: "incidents", icon: }, { name: "Status pages", path: "status", icon: }, { name: "Maintenance", path: "maintenance", icon: }, - { name: "Page speed", path: "pagespeed", icon: }, { name: "Integrations", path: "integrations", icon: }, + { + name: "Account", + icon: , + nested: [ + { name: "Profile", path: "account/profile", icon: }, + { name: "Password", path: "account/password", icon: }, + { name: "Team", path: "account/team", icon: }, + ], + }, +]; + +const other = [ { name: "Support", path: "support", icon: }, { name: "Settings", path: "settings", icon: }, ]; -const icons = { - Profile: , - Team: , - Password: , - Logout: , -}; - /** * @component * Sidebar component serves as a sidebar containing a menu. @@ -55,23 +80,8 @@ function Sidebar() { 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} event - The event triggered by clicking the user menu button. - */ - const handleOpenUserMenu = (event) => { - setAnchorElUser(event.currentTarget); - }; + const [open, setOpen] = useState({ Dashboard: false, Account: false }); /** * Handles logging out the user @@ -84,113 +94,180 @@ function Sidebar() { navigate("/login"); }; - /** - * 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; - } - }; + useEffect(() => { + if ( + location.pathname.includes("monitors") || + location.pathname.includes("pagespeed") + ) + setOpen((prev) => ({ ...prev, Dashboard: true })); + else if (location.pathname.includes("/account")) + setOpen((prev) => ({ ...prev, Account: true })); + }, []); return ( - - - {menu.map((item) => ( - - item.path === "support" - ? window.open( - "https://github.com/bluewave-labs/bluewave-uptime", - "_blank", - "noreferrer" - ) - : navigate(`/${item.path}`) - } - > - {item.icon} - {item.name} - - ))} - + + + + {/* menu */} + + Menu + + } > - - - + {menu.map((item) => + item.path ? ( + navigate(`/${item.path}`)} + sx={{ + gap: theme.gap.medium, + borderRadius: `${theme.shape.borderRadius}px`, + }} + > + {item.icon} + {item.name} + + ) : ( + + + setOpen((prev) => ({ + ...prev, + [`${item.name}`]: !prev[`${item.name}`], + })) + } + sx={{ + gap: theme.gap.medium, + borderRadius: `${theme.shape.borderRadius}px`, + }} + > + {item.icon} + {item.name} + {open[`${item.name}`] ? : } + + + + {item.nested.map((child) => { + if ( + child.name === "Team" && + authState.user?.role && + !authState.user.role.includes("admin") + ) { + return null; + } + + return ( + navigate(`/${child.path}`)} + sx={{ + gap: theme.gap.medium, + borderRadius: `${theme.shape.borderRadius}px`, + pl: theme.gap.small, + }} + > + + {child.icon} + + {child.name} + + ); + })} + + + + ) + )} + + + {/* other */} + + Other + + } + > + {other.map((item) => ( + + item.path === "support" + ? window.open( + "https://github.com/bluewave-labs/bluewave-uptime", + "_blank", + "noreferrer" + ) + : navigate(`/${item.path}`) + } + sx={{ + gap: theme.gap.medium, + borderRadius: `${theme.shape.borderRadius}px`, + }} + > + {item.icon} + {item.name} + + ))} + + + + + + {authState.user?.firstName} {authState.user?.lastName} - - - - - {settings.map((setting) => ( - handleCloseUserMenu(setting)}> - {icons[setting]} - - {setting} - - - ))} - + + {authState.user?.role} + + + + + + + + ); } diff --git a/Client/src/Layouts/HomeLayout/index.css b/Client/src/Layouts/HomeLayout/index.css index 2798bd292..f143b3fd9 100644 --- a/Client/src/Layouts/HomeLayout/index.css +++ b/Client/src/Layouts/HomeLayout/index.css @@ -25,7 +25,11 @@ border-radius: var(--env-var-radius-1); background-color: var(--env-var-color-8); - padding: var(--env-var-spacing-1) var(--env-var-spacing-1-plus); + padding: var(--env-var-spacing-1) 0; +} +.home-layout aside > *:not(:first-child) { + padding-left: var(--env-var-spacing-1-plus); + padding-right: var(--env-var-spacing-1-plus); } .home-layout > div { diff --git a/Client/src/assets/icons/dashboard.svg b/Client/src/assets/icons/dashboard.svg new file mode 100644 index 000000000..8958e90ed --- /dev/null +++ b/Client/src/assets/icons/dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/Client/src/assets/icons/down-arrow.svg b/Client/src/assets/icons/down-arrow.svg index 7c6a715ed..59b4b6bc5 100644 --- a/Client/src/assets/icons/down-arrow.svg +++ b/Client/src/assets/icons/down-arrow.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/incidents.svg b/Client/src/assets/icons/incidents.svg index 054d96b06..ffe04d09f 100644 --- a/Client/src/assets/icons/incidents.svg +++ b/Client/src/assets/icons/incidents.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/integrations.svg b/Client/src/assets/icons/integrations.svg index 96edfb485..50e817f00 100644 --- a/Client/src/assets/icons/integrations.svg +++ b/Client/src/assets/icons/integrations.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/lock.svg b/Client/src/assets/icons/lock.svg index 38e8e1df0..eb625f0ee 100644 --- a/Client/src/assets/icons/lock.svg +++ b/Client/src/assets/icons/lock.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/logout.svg b/Client/src/assets/icons/logout.svg index bf4183d73..3f3b69c49 100644 --- a/Client/src/assets/icons/logout.svg +++ b/Client/src/assets/icons/logout.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/maintenance.svg b/Client/src/assets/icons/maintenance.svg index 6d0262f3f..9486f6086 100644 --- a/Client/src/assets/icons/maintenance.svg +++ b/Client/src/assets/icons/maintenance.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/up-arrow.svg b/Client/src/assets/icons/up-arrow.svg new file mode 100644 index 000000000..0f8f3bc34 --- /dev/null +++ b/Client/src/assets/icons/up-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/Client/src/assets/icons/user-edit.svg b/Client/src/assets/icons/user-edit.svg new file mode 100644 index 000000000..cbd1a252f --- /dev/null +++ b/Client/src/assets/icons/user-edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/Client/src/assets/icons/user-two.svg b/Client/src/assets/icons/user-two.svg index 8e40622c3..031b22787 100644 --- a/Client/src/assets/icons/user-two.svg +++ b/Client/src/assets/icons/user-two.svg @@ -1,3 +1,3 @@ - + diff --git a/Client/src/assets/icons/user.svg b/Client/src/assets/icons/user.svg index 51e0e7b11..231c89d40 100644 --- a/Client/src/assets/icons/user.svg +++ b/Client/src/assets/icons/user.svg @@ -1,3 +1,3 @@ - +