frontend/containers/GenericToolbar/index.tsx (view raw)
1import {useState, useEffect} from 'react';
2import {useRouter} from 'next/router';
3import {makeStyles} from '@material-ui/core/styles';
4import AppBar from '@material-ui/core/AppBar';
5import Toolbar from '@material-ui/core/Toolbar';
6import Typography from '@material-ui/core/Typography';
7import IconButton from '@material-ui/core/IconButton';
8import Avatar from '@material-ui/core/Avatar';
9import Icon from '@material-ui/core/Icon';
10import useProfile from '../../hooks/useProfile';
11import GenericMenu from '../GenericMenu';
12import {ActionType} from '../GenericMenu/Action';
13import useBannerStore from '../../stores/useBannerStore';
14import Banner from '../../components/Banner';
15import useSettings from '../../hooks/useSettings';
16import useLangStore from '../../stores/useLangStore';
17
18const GenericToolbar = ({
19 title,
20 actions = [],
21 goBack = null,
22}: {
23 title: string;
24 actions: Array<ActionType>;
25 goBack: () => void | null;
26}) => {
27 const router = useRouter();
28 const [anchorEl, setAnchorEl] = useState(null);
29 const bannerOffset = useBannerStore(s => s.offset);
30 const bannerHeight = useBannerStore(s => s.height);
31 const language = useLangStore(s => s.language);
32 const classes = useStyles({bannerOffset, bannerHeight});
33 const {user} = useProfile();
34 const settings = useSettings();
35 const [lastAnnouncementSeen, setLastAnnouncementSeen] = useState(
36 typeof localStorage !== 'undefined'
37 ? localStorage.getItem('lastAnnouncementSeen')
38 : ''
39 );
40 const announcement = settings?.announcement || '';
41 const showAnnouncement =
42 language === 'FR' &&
43 announcement !== '' &&
44 announcement !== lastAnnouncementSeen;
45
46 const onBannerClear = () => {
47 if (typeof announcement != 'undefined') {
48 localStorage.setItem('lastAnnouncementSeen', String(announcement));
49 }
50 setLastAnnouncementSeen(announcement);
51 };
52
53 const userInfos = user
54 ? [{label: user.username, id: 'Email'}, {divider: true}]
55 : [];
56
57 useEffect(() => {
58 window.scrollTo(0, 0);
59 }, []);
60
61 return (
62 <AppBar
63 position="fixed"
64 color="primary"
65 className={classes.appbar}
66 id="Menu"
67 >
68 <Banner
69 message={announcement}
70 open={showAnnouncement}
71 onClear={onBannerClear}
72 />
73 <Toolbar>
74 {goBack && (
75 <IconButton
76 edge="start"
77 className={classes.goBack}
78 onClick={() =>
79 router.basePath.split('/').length > 2
80 ? router.back()
81 : router.push('/dashboard')
82 }
83 >
84 <Icon>arrow_back</Icon>
85 </IconButton>
86 )}
87 <div className={classes.name}>
88 <Typography variant="h6" noWrap id="MenuHeaderTitle">
89 {title}
90 </Typography>
91 </div>
92 {actions.length > 0 && (
93 <>
94 <IconButton
95 color="inherit"
96 edge="end"
97 id="MenuMoreInfo"
98 onClick={e => setAnchorEl(e.currentTarget)}
99 >
100 {user ? (
101 <Avatar className={classes.avatar}>
102 {`${user.username[0]}`.toUpperCase()}
103 </Avatar>
104 ) : (
105 <Icon>more_vert</Icon>
106 )}
107 </IconButton>
108
109 <GenericMenu
110 anchorEl={anchorEl}
111 setAnchorEl={setAnchorEl}
112 actions={[...userInfos, ...actions, {divider: true}]}
113 />
114 </>
115 )}
116 </Toolbar>
117 </AppBar>
118 );
119};
120
121const useStyles = makeStyles(theme => ({
122 appbar: ({bannerHeight, bannerOffset}) => ({
123 minHeight: theme.mixins.toolbar.minHeight,
124 transition: 'height 0.3s ease',
125 display: 'block',
126 marginTop: bannerOffset - bannerHeight,
127 }),
128 name: {
129 flexGrow: 1,
130 display: 'flex',
131 alignItems: 'center',
132 },
133 avatar: {
134 width: theme.spacing(3),
135 height: theme.spacing(3),
136 fontSize: 16,
137 },
138 goBack: {
139 color: theme.palette.common.white,
140 },
141}));
142
143export default GenericToolbar;