feat: add account dropdown menu with logout link
This commit is contained in:

committed by
Ömer Faruk Aydın

parent
22e1fe5c44
commit
782dba1f5e
57
packages/web/src/components/AccountDropdownMenu/index.tsx
Normal file
57
packages/web/src/components/AccountDropdownMenu/index.tsx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
import Menu, { MenuProps } from '@mui/material/Menu';
|
||||||
|
|
||||||
|
import * as URLS from 'config/urls';
|
||||||
|
import useAuthentication from 'hooks/useAuthentication';
|
||||||
|
import useFormatMessage from 'hooks/useFormatMessage';
|
||||||
|
|
||||||
|
type AccountDropdownMenuProps = {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
anchorEl: MenuProps["anchorEl"];
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountDropdownMenu(props: AccountDropdownMenuProps): React.ReactElement {
|
||||||
|
const formatMessage = useFormatMessage();
|
||||||
|
const authentication = useAuthentication();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const {
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
anchorEl,
|
||||||
|
id
|
||||||
|
} = props
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
authentication.updateToken('');
|
||||||
|
onClose();
|
||||||
|
|
||||||
|
navigate(URLS.LOGIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
id={id}
|
||||||
|
keepMounted
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
open={open}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={logout}>{formatMessage('accountDropdownMenu.logout')}</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AccountDropdownMenu;
|
@@ -8,8 +8,9 @@ import IconButton from '@mui/material/IconButton';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import MenuIcon from '@mui/icons-material/Menu';
|
import MenuIcon from '@mui/icons-material/Menu';
|
||||||
import MenuOpenIcon from '@mui/icons-material/MenuOpen';
|
import MenuOpenIcon from '@mui/icons-material/MenuOpen';
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||||
|
|
||||||
|
import AccountDropdownMenu from 'components/AccountDropdownMenu';
|
||||||
import Container from 'components/Container';
|
import Container from 'components/Container';
|
||||||
import HideOnScroll from 'components/HideOnScroll';
|
import HideOnScroll from 'components/HideOnScroll';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
@@ -21,6 +22,8 @@ type AppBarProps = {
|
|||||||
maxWidth?: ContainerProps["maxWidth"];
|
maxWidth?: ContainerProps["maxWidth"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const accountMenuId = 'account-menu';
|
||||||
|
|
||||||
export default function AppBar(props: AppBarProps): React.ReactElement {
|
export default function AppBar(props: AppBarProps): React.ReactElement {
|
||||||
const {
|
const {
|
||||||
drawerOpen,
|
drawerOpen,
|
||||||
@@ -32,6 +35,18 @@ export default function AppBar(props: AppBarProps): React.ReactElement {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });
|
const matchSmallScreens = useMediaQuery(theme.breakpoints.down('md'), { noSsr: true });
|
||||||
|
|
||||||
|
const [accountMenuAnchorElement, setAccountMenuAnchorElement] = React.useState<null | HTMLElement>(null);
|
||||||
|
|
||||||
|
const isMenuOpen = Boolean(accountMenuAnchorElement);
|
||||||
|
|
||||||
|
const handleAccountMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setAccountMenuAnchorElement(event.currentTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAccountMenuClose = () => {
|
||||||
|
setAccountMenuAnchorElement(null);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HideOnScroll>
|
<HideOnScroll>
|
||||||
<MuiAppBar>
|
<MuiAppBar>
|
||||||
@@ -61,12 +76,21 @@ export default function AppBar(props: AppBarProps): React.ReactElement {
|
|||||||
size="large"
|
size="large"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="open settings"
|
onClick={handleAccountMenuOpen}
|
||||||
|
aria-controls={accountMenuId}
|
||||||
|
aria-label="open profile menu"
|
||||||
>
|
>
|
||||||
<SettingsIcon />
|
<AccountCircleIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
<AccountDropdownMenu
|
||||||
|
anchorEl={accountMenuAnchorElement}
|
||||||
|
id={accountMenuId}
|
||||||
|
open={isMenuOpen}
|
||||||
|
onClose={handleAccountMenuClose}
|
||||||
|
/>
|
||||||
</MuiAppBar>
|
</MuiAppBar>
|
||||||
</HideOnScroll>
|
</HideOnScroll>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import MuiAppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export default function Layout({ children }: LayoutProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MuiAppBar>
|
<AppBar>
|
||||||
<Container maxWidth="lg" disableGutters>
|
<Container maxWidth="lg" disableGutters>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography
|
<Typography
|
||||||
@@ -29,7 +29,7 @@ export default function Layout({ children }: LayoutProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>
|
</Container>
|
||||||
</MuiAppBar>
|
</AppBar>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"brandText": "Automatisch",
|
"brandText": "Automatisch",
|
||||||
"searchPlaceholder": "Search",
|
"searchPlaceholder": "Search",
|
||||||
|
"accountDropdownMenu.logout": "Logout",
|
||||||
"drawer.dashboard": "Dashboard",
|
"drawer.dashboard": "Dashboard",
|
||||||
"drawer.flows": "Flows",
|
"drawer.flows": "Flows",
|
||||||
"drawer.apps": "My Apps",
|
"drawer.apps": "My Apps",
|
||||||
|
Reference in New Issue
Block a user