account tab fix

This commit is contained in:
Alex Holliday committed 2026-02-10 23:24:51 +00:00
1 parent 71f3c90472
commit 442fc2ce22
2 files changed
+117 -205

No files matched your search

+111 -204
View File
@@ -1,103 +1,75 @@
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import Tooltip from "@mui/material/Tooltip";
import IconButton from "@mui/material/IconButton";
import { Avatar, Icon } from "@/Components/v2/design-elements";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import { MoreVertical, LogOut } from "lucide-react";
import { useTheme } from "@mui/material";
import { useSelector } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import { useNavigate } from "react-router";
import { MoreVertical, LogOut } from "lucide-react";
import { Avatar, Icon } from "@/Components/v2/design-elements";
import { clearAuthState } from "@/Features/Auth/authSlice.js";
import { useDispatch } from "react-redux";
import type { RootState } from "@/Types/state.js";
const getFilteredAccountMenuItems = (user: any, items: any[]) => {
if (!user) return [];
let filtered = [...items];
if (user.role?.includes("demo")) {
filtered = filtered.filter((item) => item.name !== "Password");
}
if (!user.role?.includes("superadmin")) {
filtered = filtered.filter((item) => item.name !== "Team");
}
return filtered;
};
const getRoleDisplayText = (user: any, t: Function) => {
if (!user?.role) return "";
if (user.role.includes("superadmin"))
return t("components.sidebar.authFooter.roles.superAdmin");
if (user.role.includes("admin")) return t("components.sidebar.authFooter.roles.admin");
if (user.role.includes("user"))
return t("components.sidebar.authFooter.roles.teamMember");
if (user.role.includes("demo"))
return t("components.sidebar.authFooter.roles.demoUser");
return user.role;
};
export const AuthFooter = ({
collapsed,
accountMenuItems,
}: {
interface AuthFooterProps {
collapsed: boolean;
accountMenuItems: any[];
}) => {
accountMenuItems: Array<{
name: string;
path: string;
icon: React.ReactNode;
}>;
}
export const AuthFooter = ({ collapsed, accountMenuItems }: AuthFooterProps) => {
const { t } = useTranslation();
const theme = useTheme();
const authState = useSelector((state: RootState) => state.auth);
const user = useSelector((state: RootState) => state.auth.user);
const navigate = useNavigate();
const dispatch = useDispatch();
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const openPopup = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
const menuOpen = Boolean(anchorEl);
const handleMenuOpen = (e: React.MouseEvent<HTMLElement>) =>
setAnchorEl(e.currentTarget);
const handleMenuClose = () => setAnchorEl(null);
const handleNavigate = (path: string) => {
handleMenuClose();
navigate(path);
};
const closePopup = () => {
setAnchorEl(null);
};
const logout = async () => {
const handleLogout = () => {
dispatch(clearAuthState());
navigate("/login");
};
const renderAccountMenuItems = (user: any, items: any[]) => {
const filteredItems = getFilteredAccountMenuItems(user, items);
return filteredItems.map((item) => (
<MenuItem
key={item.name}
onClick={() => {
closePopup();
navigate(item.path);
}}
sx={{
gap: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
"& svg": {
stroke: theme.palette.text.secondary,
},
}}
>
{item.icon}
{item.name}
</MenuItem>
));
const getRoleText = () => {
const role = user?.role ?? "";
if (role.includes("superadmin"))
return t("components.sidebar.authFooter.roles.superAdmin");
if (role.includes("admin")) return t("components.sidebar.authFooter.roles.admin");
if (role.includes("user")) return t("components.sidebar.authFooter.roles.teamMember");
if (role.includes("demo")) return t("components.sidebar.authFooter.roles.demoUser");
return role;
};
const filteredMenuItems = accountMenuItems.filter((item) => {
if (!user) return false;
if (item.name === "Password" && user.role?.includes("demo")) return false;
if (item.name === "Team" && !user.role?.includes("superadmin")) return false;
return true;
});
const menuItemSx = {
gap: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
"& svg": { stroke: theme.palette.text.secondary },
};
return (
<Stack
direction="row"
@@ -105,164 +77,99 @@ export const AuthFooter = ({
py={theme.spacing(4)}
px={theme.spacing(8)}
gap={theme.spacing(2)}
borderRadius={theme.shape.borderRadius}
boxSizing={"border-box"}
>
<Avatar
small={true}
onClick={(e: any) => {
openPopup(e);
}}
sx={{
cursor: collapsed ? "pointer" : "default",
}}
small
onClick={collapsed ? handleMenuOpen : undefined}
sx={{ cursor: collapsed ? "pointer" : "default" }}
/>
<Stack
direction={"row"}
alignItems={"center"}
gap={theme.spacing(2)}
minWidth={0}
maxWidth={collapsed ? 0 : "100%"}
sx={{
opacity: collapsed ? 0 : 1,
transition: "opacity 300ms ease, max-width 300ms ease",
transitionDelay: collapsed ? "0ms" : "300ms",
}}
>
{!collapsed && (
<Stack
ml={theme.spacing(2)}
sx={{
maxWidth: "50%",
overflow: "hidden",
}}
direction="row"
alignItems="center"
gap={theme.spacing(2)}
minWidth={0}
flex={1}
>
<Typography
fontWeight={500}
lineHeight={1}
sx={{
display: "block",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
color: theme.palette.text.primary,
}}
<Stack
minWidth={0}
flex={1}
>
{authState.user?.firstName} {authState.user?.lastName}
</Typography>
<Typography
textOverflow="ellipsis"
overflow="hidden"
whiteSpace="nowrap"
sx={{
textTransform: "capitalize",
color: theme.palette.text.secondary,
}}
>
{getRoleDisplayText(authState.user, t)}
</Typography>
</Stack>
<Tooltip
title={t("components.sidebar.authFooter.navControls")}
disableInteractive
>
<Typography
fontWeight={500}
noWrap
sx={{ color: theme.palette.text.primary }}
>
{user?.firstName} {user?.lastName}
</Typography>
<Typography
noWrap
sx={{ textTransform: "capitalize", color: theme.palette.text.secondary }}
>
{getRoleText()}
</Typography>
</Stack>
<IconButton
onClick={handleMenuOpen}
sx={{
ml: "50px",
"&:focus": { outline: "none" },
alignSelf: "center",
"& svg": {
stroke: theme.palette.text.secondary,
},
"& svg": { stroke: theme.palette.text.secondary },
}}
onClick={(event) => openPopup(event)}
>
<Icon
icon={MoreVertical}
size={22}
/>
</IconButton>
</Tooltip>
</Stack>
</Stack>
)}
<Menu
className="sidebar-popup"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={closePopup}
open={menuOpen}
onClose={handleMenuClose}
disableScrollLock
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
anchorOrigin={{ vertical: "top", horizontal: "right" }}
slotProps={{
paper: {
sx: {
marginTop: theme.spacing(-4),
marginLeft: collapsed ? theme.spacing(2) : 0,
},
},
}}
MenuListProps={{
sx: {
p: 2,
"& li": { m: 0 },
"& li:has(.MuiBox-root):hover": {
backgroundColor: "transparent",
},
},
}}
sx={{
ml: theme.spacing(4),
paper: { sx: { mt: theme.spacing(-4), ml: collapsed ? theme.spacing(2) : 0 } },
}}
MenuListProps={{ sx: { p: 2, "& li": { m: 0 } } }}
sx={{ ml: theme.spacing(4) }}
>
{collapsed && (
<MenuItem sx={{ cursor: "default", minWidth: "50%" }}>
<Box
mb={theme.spacing(2)}
sx={{
minWidth: "50%",
maxWidth: "max-content",
overflow: "visible",
whiteSpace: "nowrap",
}}
<Box
px={2}
pb={2}
sx={{ pointerEvents: "none" }}
>
<Typography
fontWeight={500}
fontSize={13}
>
<Typography
component="span"
fontWeight={500}
fontSize={13}
sx={{
display: "block",
whiteSpace: "nowrap",
overflow: "visible",
textOverflow: "clip",
}}
>
{authState.user?.firstName} {authState.user?.lastName}
</Typography>
<Typography
sx={{
textTransform: "capitalize",
fontSize: 12,
whiteSpace: "nowrap",
overflow: "visible",
}}
>
{authState.user?.role}
</Typography>
</Box>
</MenuItem>
{user?.firstName} {user?.lastName}
</Typography>
<Typography
fontSize={12}
sx={{ textTransform: "capitalize" }}
>
{getRoleText()}
</Typography>
</Box>
)}
{renderAccountMenuItems(authState.user, accountMenuItems)}
{filteredMenuItems.map((item) => (
<MenuItem
key={item.name}
onClick={() => handleNavigate(item.path)}
sx={menuItemSx}
>
{item.icon}
{item.name}
</MenuItem>
))}
<MenuItem
onClick={logout}
sx={{
gap: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
"& svg": {
stroke: theme.palette.text.secondary,
},
}}
onClick={handleLogout}
sx={menuItemSx}
>
<Icon
icon={LogOut}
+6 -1
View File
@@ -1,5 +1,5 @@
import { BasePage, Tabs, Tab } from "@/Components/v2/design-elements";
import { useState } from "react";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { TabProfile } from "./TabProfile";
import { TabPassword } from "./TabPassword";
@@ -19,6 +19,11 @@ const Account = ({ open = "profile" }: AccountProps) => {
const { t } = useTranslation();
const [activeTab, setActiveTab] = useState<number>(TAB_MAP[open]);
// Sync activeTab when open prop changes (e.g., navigating from sidebar)
useEffect(() => {
setActiveTab(TAB_MAP[open]);
}, [open]);
return (
<BasePage>
<Tabs