mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-12 11:23:42 +08:00
feat: add new theme berry (#860)
* feat: add theme berry * docs: add development notes * fix: fix blank page * chore: update implementation * fix: fix package.json * chore: update ui copy --------- Co-authored-by: JustSong <songquanpeng@foxmail.com>
This commit is contained in:
173
web/berry/src/layout/MainLayout/Header/ProfileSection/index.js
Normal file
173
web/berry/src/layout/MainLayout/Header/ProfileSection/index.js
Normal file
@@ -0,0 +1,173 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
// material-ui
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
Avatar,
|
||||
Chip,
|
||||
ClickAwayListener,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Paper,
|
||||
Popper,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
// project imports
|
||||
import MainCard from 'ui-component/cards/MainCard';
|
||||
import Transitions from 'ui-component/extended/Transitions';
|
||||
import User1 from 'assets/images/users/user-round.svg';
|
||||
import useLogin from 'hooks/useLogin';
|
||||
|
||||
// assets
|
||||
import { IconLogout, IconSettings, IconUserScan } from '@tabler/icons-react';
|
||||
|
||||
// ==============================|| PROFILE MENU ||============================== //
|
||||
|
||||
const ProfileSection = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const customization = useSelector((state) => state.customization);
|
||||
const { logout } = useLogin();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
/**
|
||||
* anchorRef is used on different componets and specifying one type leads to other components throwing an error
|
||||
* */
|
||||
const anchorRef = useRef(null);
|
||||
const handleLogout = async () => {
|
||||
logout();
|
||||
};
|
||||
|
||||
const handleClose = (event) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const prevOpen = useRef(open);
|
||||
useEffect(() => {
|
||||
if (prevOpen.current === true && open === false) {
|
||||
anchorRef.current.focus();
|
||||
}
|
||||
|
||||
prevOpen.current = open;
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Chip
|
||||
sx={{
|
||||
height: '48px',
|
||||
alignItems: 'center',
|
||||
borderRadius: '27px',
|
||||
transition: 'all .2s ease-in-out',
|
||||
borderColor: theme.palette.primary.light,
|
||||
backgroundColor: theme.palette.primary.light,
|
||||
'&[aria-controls="menu-list-grow"], &:hover': {
|
||||
borderColor: theme.palette.primary.main,
|
||||
background: `${theme.palette.primary.main}!important`,
|
||||
color: theme.palette.primary.light,
|
||||
'& svg': {
|
||||
stroke: theme.palette.primary.light
|
||||
}
|
||||
},
|
||||
'& .MuiChip-label': {
|
||||
lineHeight: 0
|
||||
}
|
||||
}}
|
||||
icon={
|
||||
<Avatar
|
||||
src={User1}
|
||||
sx={{
|
||||
...theme.typography.mediumAvatar,
|
||||
margin: '8px 0 8px 8px !important',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'menu-list-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
color="inherit"
|
||||
/>
|
||||
}
|
||||
label={<IconSettings stroke={1.5} size="1.5rem" color={theme.palette.primary.main} />}
|
||||
variant="outlined"
|
||||
ref={anchorRef}
|
||||
aria-controls={open ? 'menu-list-grow' : undefined}
|
||||
aria-haspopup="true"
|
||||
onClick={handleToggle}
|
||||
color="primary"
|
||||
/>
|
||||
<Popper
|
||||
placement="bottom-end"
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
transition
|
||||
disablePortal
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 14]
|
||||
}
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps }) => (
|
||||
<Transitions in={open} {...TransitionProps}>
|
||||
<Paper>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MainCard border={false} elevation={16} content={false} boxShadow shadow={theme.shadows[16]}>
|
||||
<List
|
||||
component="nav"
|
||||
sx={{
|
||||
width: '100%',
|
||||
maxWidth: 350,
|
||||
minWidth: 150,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: '10px',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
minWidth: '100%'
|
||||
},
|
||||
'& .MuiListItemButton-root': {
|
||||
mt: 0.5
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ListItemButton sx={{ borderRadius: `${customization.borderRadius}px` }} onClick={() => navigate('/panel/profile')}>
|
||||
<ListItemIcon>
|
||||
<IconUserScan stroke={1.5} size="1.3rem" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography variant="body2">设置</Typography>} />
|
||||
</ListItemButton>
|
||||
|
||||
<ListItemButton sx={{ borderRadius: `${customization.borderRadius}px` }} onClick={handleLogout}>
|
||||
<ListItemIcon>
|
||||
<IconLogout stroke={1.5} size="1.3rem" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={<Typography variant="body2">登出</Typography>} />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
</MainCard>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Transitions>
|
||||
)}
|
||||
</Popper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfileSection;
|
||||
Reference in New Issue
Block a user