mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
fixed jumpy buttons, moved user profile to its own component
This commit is contained in:
55
interface/src/app/main/UserProfile.tsx
Normal file
55
interface/src/app/main/UserProfile.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { memo, useCallback, useContext } from 'react';
|
||||||
|
|
||||||
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
|
import { Avatar, Box, Button, List, ListItem, ListItemText } from '@mui/material';
|
||||||
|
|
||||||
|
import { AuthenticatedContext } from '@/contexts/authentication';
|
||||||
|
import { SectionContent, useLayoutTitle } from 'components';
|
||||||
|
import { LanguageSelector } from 'components/inputs';
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
|
const UserProfileComponent = () => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const { me, signOut } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
|
useLayoutTitle(LL.USER(1));
|
||||||
|
|
||||||
|
const handleSignOut = useCallback(() => {
|
||||||
|
signOut(true);
|
||||||
|
}, [signOut]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SectionContent>
|
||||||
|
<Box padding={2} justifyContent="center" flexDirection="column">
|
||||||
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
|
<List sx={{ flexGrow: 1 }}>
|
||||||
|
<ListItem disablePadding>
|
||||||
|
<Avatar sx={{ bgcolor: '#9e9e9e', color: 'white' }}>
|
||||||
|
<PersonIcon />
|
||||||
|
</Avatar>
|
||||||
|
<ListItemText
|
||||||
|
sx={{ pl: 2, color: '#2196f3' }}
|
||||||
|
primary={me.username}
|
||||||
|
secondary={'(' + (me.admin ? LL.ADMINISTRATOR() : LL.GUEST()) + ')'}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
<LanguageSelector />
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
sx={{ mt: 2 }}
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
onClick={handleSignOut}
|
||||||
|
>
|
||||||
|
{LL.SIGN_OUT()}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</SectionContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserProfile = memo(UserProfileComponent);
|
||||||
|
|
||||||
|
export default UserProfile;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { memo, useCallback, useContext, useMemo, useState } from 'react';
|
import { memo, useCallback, useContext, useState } from 'react';
|
||||||
|
|
||||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||||
import AssessmentIcon from '@mui/icons-material/Assessment';
|
import AssessmentIcon from '@mui/icons-material/Assessment';
|
||||||
@@ -7,51 +7,21 @@ import ConstructionIcon from '@mui/icons-material/Construction';
|
|||||||
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
|
||||||
import LiveHelpIcon from '@mui/icons-material/LiveHelp';
|
import LiveHelpIcon from '@mui/icons-material/LiveHelp';
|
||||||
import MoreTimeIcon from '@mui/icons-material/MoreTime';
|
import MoreTimeIcon from '@mui/icons-material/MoreTime';
|
||||||
import PersonIcon from '@mui/icons-material/Person';
|
|
||||||
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
|
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
|
||||||
import SensorsIcon from '@mui/icons-material/Sensors';
|
import SensorsIcon from '@mui/icons-material/Sensors';
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import StarIcon from '@mui/icons-material/Star';
|
import StarIcon from '@mui/icons-material/Star';
|
||||||
import {
|
import { Box, Divider, List, ListItemButton, ListItemText } from '@mui/material';
|
||||||
Avatar,
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Divider,
|
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Popover
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
import { LanguageSelector } from 'components/inputs';
|
|
||||||
import LayoutMenuItem from 'components/layout/LayoutMenuItem';
|
import LayoutMenuItem from 'components/layout/LayoutMenuItem';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
const LayoutMenuComponent = () => {
|
const LayoutMenuComponent = () => {
|
||||||
const { me, signOut } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
|
||||||
const [menuOpen, setMenuOpen] = useState(true);
|
const [menuOpen, setMenuOpen] = useState(true);
|
||||||
|
|
||||||
const open = useMemo(() => Boolean(anchorEl), [anchorEl]);
|
|
||||||
const id = useMemo(() => (anchorEl ? 'app-menu-popover' : undefined), [anchorEl]);
|
|
||||||
|
|
||||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
|
||||||
setAnchorEl(event.currentTarget);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
|
||||||
setAnchorEl(null);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSignOut = useCallback(() => {
|
|
||||||
signOut(true);
|
|
||||||
}, [signOut]);
|
|
||||||
|
|
||||||
const handleMenuToggle = useCallback(() => {
|
const handleMenuToggle = useCallback(() => {
|
||||||
setMenuOpen((prev) => !prev);
|
setMenuOpen((prev) => !prev);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -139,64 +109,9 @@ const LayoutMenuComponent = () => {
|
|||||||
to="/settings"
|
to="/settings"
|
||||||
/>
|
/>
|
||||||
<LayoutMenuItem icon={LiveHelpIcon} label={LL.HELP()} to={`/help`} />
|
<LayoutMenuItem icon={LiveHelpIcon} label={LL.HELP()} to={`/help`} />
|
||||||
</List>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<List>
|
<LayoutMenuItem icon={AccountCircleIcon} label={me.username} to={`/user`} />
|
||||||
<ListItem disablePadding>
|
|
||||||
<ListItemButton component="button" onClick={handleClick}>
|
|
||||||
<ListItemIcon sx={{ color: '#9e9e9e' }}>
|
|
||||||
<AccountCircleIcon />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText sx={{ color: '#2196f3' }}>{me.username}</ListItemText>
|
|
||||||
</ListItemButton>
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
</List>
|
||||||
<Popover
|
|
||||||
id={id}
|
|
||||||
open={open}
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
onClose={handleClose}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: 'bottom',
|
|
||||||
horizontal: 'center'
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: 'top',
|
|
||||||
horizontal: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
padding={2}
|
|
||||||
justifyContent="center"
|
|
||||||
flexDirection="column"
|
|
||||||
sx={{
|
|
||||||
borderRadius: 3,
|
|
||||||
border: '3px solid grey'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
fullWidth
|
|
||||||
color="primary"
|
|
||||||
onClick={handleSignOut}
|
|
||||||
>
|
|
||||||
{LL.SIGN_OUT()}
|
|
||||||
</Button>
|
|
||||||
<List>
|
|
||||||
<ListItem disablePadding>
|
|
||||||
<Avatar sx={{ bgcolor: '#9e9e9e', color: 'white' }}>
|
|
||||||
<PersonIcon />
|
|
||||||
</Avatar>
|
|
||||||
<ListItemText
|
|
||||||
sx={{ pl: 2, color: '#2196f3' }}
|
|
||||||
primary={me.username}
|
|
||||||
secondary={'(' + (me.admin ? LL.ADMINISTRATOR() : LL.GUEST()) + ')'}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
|
||||||
<LanguageSelector />
|
|
||||||
</Box>
|
|
||||||
</Popover>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,13 +27,11 @@ const LayoutMenuItemComponent = ({
|
|||||||
const buttonStyles: SxProps<Theme> = useMemo(
|
const buttonStyles: SxProps<Theme> = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
transition: 'all 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)',
|
transition: 'all 0.05s cubic-bezier(0.55, 0.085, 0.68, 0.53)',
|
||||||
transform: selected ? 'scale(1.02)' : 'scale(1)',
|
|
||||||
backgroundColor: selected ? 'rgba(144, 202, 249, 0.1)' : 'transparent',
|
backgroundColor: selected ? 'rgba(144, 202, 249, 0.1)' : 'transparent',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
margin: '2px 8px',
|
margin: '2px 8px',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: 'rgba(68, 82, 211, 0.39)',
|
backgroundColor: 'rgba(68, 82, 211, 0.39)'
|
||||||
transform: selected ? 'scale(1.02)' : 'scale(1.01)'
|
|
||||||
},
|
},
|
||||||
'&::before': {
|
'&::before': {
|
||||||
content: '""',
|
content: '""',
|
||||||
|
|||||||
Reference in New Issue
Block a user