201 lines
6.7 KiB
JavaScript
201 lines
6.7 KiB
JavaScript
import { PureComponent } from 'react';
|
|
import Avatar from '@mui/material/Avatar';
|
|
import Badge from '@mui/material/Badge';
|
|
import Box from '@mui/material/Box';
|
|
import IconButton from '@mui/material/IconButton';
|
|
import Menu from '@mui/material/Menu';
|
|
import MenuItem from '@mui/material/MenuItem';
|
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
import LogoutIcon from '@mui/icons-material/Logout';
|
|
import BusinessIcon from '@mui/icons-material/Business';
|
|
import SettingsIcon from '@mui/icons-material/Settings';
|
|
import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';
|
|
import SystemUpdateAltIcon from '@mui/icons-material/SystemUpdateAlt';
|
|
import Switch from '@mui/material/Switch';
|
|
import Divider from '@mui/material/Divider';
|
|
import authAutomat, { bootstrapAuthMe } from '../automats/authAutomat';
|
|
import { helpAutomat, toggleHelp, pwaAutomat, openPwaDialog } from '../automats';
|
|
import CompanySettingsDialog from './CompanySettingsDialog';
|
|
import SettingsDialog from './settings/SettingsDialog';
|
|
import { notifyError } from '../utils/notify';
|
|
|
|
class UserMenu extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
anchorEl: null,
|
|
settingsOpen: false,
|
|
numbersOpen: false,
|
|
user: authAutomat.state.user,
|
|
helpEnabled: helpAutomat.state?.enabled ?? false,
|
|
pwaUpdateAvailable: pwaAutomat.state.needRefresh,
|
|
};
|
|
this.handleOpenMenu = this.handleOpenMenu.bind(this);
|
|
this.handleCloseMenu = this.handleCloseMenu.bind(this);
|
|
this.handleOpenSettings = this.handleOpenSettings.bind(this);
|
|
this.handleCloseSettings = this.handleCloseSettings.bind(this);
|
|
this.handleOpenNumbers = this.handleOpenNumbers.bind(this);
|
|
this.handleCloseNumbers = this.handleCloseNumbers.bind(this);
|
|
this.handleToggleHelp = this.handleToggleHelp.bind(this);
|
|
this.handleOpenPwaUpdate = this.handleOpenPwaUpdate.bind(this);
|
|
this.handleLogout = this.handleLogout.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.unsubscribeAuth = authAutomat.subscribe(this, 'user');
|
|
this.unsubscribeHelp = helpAutomat.subscribe(this, (state) => ({
|
|
helpEnabled: Boolean(state?.enabled),
|
|
}));
|
|
this.unsubscribePwa = pwaAutomat.subscribe(this, (state) => ({
|
|
pwaUpdateAvailable: Boolean(state?.needRefresh),
|
|
}));
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsubscribeAuth?.();
|
|
this.unsubscribeHelp?.();
|
|
this.unsubscribePwa?.();
|
|
}
|
|
|
|
handleOpenPwaUpdate() {
|
|
this.setState({ anchorEl: null });
|
|
openPwaDialog();
|
|
}
|
|
|
|
handleOpenMenu(event) {
|
|
this.setState({ anchorEl: event.currentTarget });
|
|
}
|
|
|
|
handleCloseMenu() {
|
|
this.setState({ anchorEl: null });
|
|
}
|
|
|
|
handleOpenSettings() {
|
|
this.setState({ anchorEl: null, settingsOpen: true });
|
|
}
|
|
|
|
handleCloseSettings() {
|
|
this.setState({ settingsOpen: false });
|
|
}
|
|
|
|
handleOpenNumbers() {
|
|
this.setState({ anchorEl: null, numbersOpen: true });
|
|
}
|
|
|
|
handleCloseNumbers() {
|
|
this.setState({ numbersOpen: false });
|
|
}
|
|
|
|
handleToggleHelp(e) {
|
|
e?.preventDefault?.();
|
|
e?.stopPropagation?.();
|
|
toggleHelp();
|
|
}
|
|
|
|
async handleLogout() {
|
|
this.setState({ anchorEl: null });
|
|
try {
|
|
await authAutomat.actions.logout();
|
|
await bootstrapAuthMe();
|
|
} catch (err) {
|
|
notifyError(err);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const { user, anchorEl, settingsOpen, numbersOpen, helpEnabled, pwaUpdateAvailable } = this.state;
|
|
const open = Boolean(anchorEl);
|
|
|
|
const pictureSrc = (() => {
|
|
const pic = user?.picture;
|
|
if (!pic || typeof pic !== 'string') return undefined;
|
|
if (pic.startsWith('http://') || pic.startsWith('https://') || pic.startsWith('data:')) {
|
|
return pic;
|
|
}
|
|
const mime = pic.startsWith('/9j/') ? 'image/jpeg' : 'image/png';
|
|
return `data:${mime};base64,${pic}`;
|
|
})();
|
|
|
|
return (
|
|
<>
|
|
<Box sx={{ px: 1.5, py: 1.5, alignSelf: 'flex-start' }}>
|
|
<IconButton
|
|
onClick={this.handleOpenMenu}
|
|
onMouseDown={(e) => e.preventDefault()}
|
|
sx={{ p: 0, width: 32, height: 32, borderRadius: '50%' }}
|
|
>
|
|
<Badge
|
|
color="primary"
|
|
variant="dot"
|
|
invisible={!pwaUpdateAvailable}
|
|
overlap="circular"
|
|
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
>
|
|
<Avatar src={pictureSrc} alt={user?.email} sx={{ width: 32, height: 32 }}>
|
|
{user?.email?.[0]?.toUpperCase()}
|
|
</Avatar>
|
|
</Badge>
|
|
</IconButton>
|
|
</Box>
|
|
<Menu
|
|
anchorEl={anchorEl}
|
|
open={open}
|
|
onClose={this.handleCloseMenu}
|
|
anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
|
|
transformOrigin={{ vertical: 'bottom', horizontal: 'left' }}
|
|
>
|
|
{pwaUpdateAvailable && (
|
|
<MenuItem onClick={this.handleOpenPwaUpdate} sx={{ bgcolor: 'action.hover' }}>
|
|
<ListItemIcon>
|
|
<SystemUpdateAltIcon fontSize="small" color="primary" />
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary="Update verfügbar"
|
|
secondary="Jetzt aktualisieren"
|
|
primaryTypographyProps={{ fontWeight: 600, color: 'primary.main' }}
|
|
/>
|
|
</MenuItem>
|
|
)}
|
|
<MenuItem disabled>{user?.email}</MenuItem>
|
|
<MenuItem disabled={!user?.selectedCompanyId} onClick={this.handleOpenSettings}>
|
|
<ListItemIcon>
|
|
<BusinessIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText>Unternehmen</ListItemText>
|
|
</MenuItem>
|
|
<MenuItem disabled={!user?.selectedCompanyId} onClick={this.handleOpenNumbers}>
|
|
<ListItemIcon>
|
|
<SettingsIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText>Einstellungen</ListItemText>
|
|
</MenuItem>
|
|
<MenuItem onClick={this.handleToggleHelp}>
|
|
<ListItemIcon>
|
|
<HelpOutlineRoundedIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText>Hilfe</ListItemText>
|
|
<Switch
|
|
edge="end"
|
|
size="small"
|
|
checked={helpEnabled}
|
|
sx={{ pointerEvents: 'none' }}
|
|
/>
|
|
</MenuItem>
|
|
<Divider />
|
|
<MenuItem onClick={this.handleLogout}>
|
|
<ListItemIcon>
|
|
<LogoutIcon fontSize="small" />
|
|
</ListItemIcon>
|
|
<ListItemText>Sign out</ListItemText>
|
|
</MenuItem>
|
|
</Menu>
|
|
<CompanySettingsDialog open={settingsOpen} onClose={this.handleCloseSettings} />
|
|
<SettingsDialog open={numbersOpen} onClose={this.handleCloseNumbers} />
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default UserMenu;
|