account tab fix
This commit is contained in:
1 parent
71f3c90472
commit
442fc2ce22
2 files changed
+117
-205
No files matched your search
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user