frontend/containers/EventBar/index.tsx (view raw)
1import {useState} from 'react';
2import {useRouter} from 'next/router';
3import Link from 'next/link';
4import {makeStyles} from '@material-ui/core/styles';
5import AppBar from '@material-ui/core/AppBar';
6import Toolbar from '@material-ui/core/Toolbar';
7import Typography from '@material-ui/core/Typography';
8import IconButton from '@material-ui/core/IconButton';
9import Tooltip from '@material-ui/core/Tooltip';
10import Avatar from '@material-ui/core/Avatar';
11import Icon from '@material-ui/core/Icon';
12import clsx from 'clsx';
13import {useTranslation} from 'react-i18next';
14import useAuthStore from '../../stores/useAuthStore';
15import useEventStore from '../../stores/useEventStore';
16import useProfile from '../../hooks/useProfile';
17import useSettings from '../../hooks/useSettings';
18import GenericMenu from '../GenericMenu';
19import EventDetails from '../EventDetails';
20import useBannerStore from '../../stores/useBannerStore';
21import Banner from '../../components/Banner';
22
23const EventBar = ({event, onAdd, onSave}) => {
24 const {t} = useTranslation();
25 const router = useRouter();
26 const [anchorEl, setAnchorEl] = useState(null);
27 const isEditing = useEventStore(s => s.isEditing);
28 const areDetailsOpened = useEventStore(s => s.areDetailsOpened);
29 const setIsEditing = useEventStore(s => s.setIsEditing);
30 const setAreDetailsOpened = useEventStore(s => s.setAreDetailsOpened);
31 const token = useAuthStore(s => s.token);
32 const {user} = useProfile();
33 const settings = useSettings();
34 const bannerOffset = useBannerStore(s => s.offset);
35 const bannerHeight = useBannerStore(s => s.height);
36 const classes = useStyles({areDetailsOpened, bannerOffset, bannerHeight});
37 const announcement = settings?.announcement || '';
38 const [lastAnnouncementSeen, setLastAnnouncementSeen] = useState(
39 typeof localStorage !== 'undefined'
40 ? localStorage.getItem('lastAnnouncementSeen')
41 : ''
42 );
43 const showAnnouncement =
44 announcement !== '' && 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 signUp = () =>
54 router.push({
55 pathname: '/auth/register',
56 state: {event: event?.id},
57 });
58 const signIn = () => router.push('/auth/login');
59 const goToDashboard = () => router.push('/dashboard');
60 const goProfile = () => router.push('/profile');
61
62 const noUserMenuActions = [
63 {
64 label: t('event.actions.add_to_my_events'),
65 onClick: () => {
66 onAdd(true);
67 },
68 id: 'AddToMyEventsTab',
69 },
70 {divider: true},
71 {
72 label: t('menu.login'),
73 onClick: signIn,
74 id: 'SignInTab',
75 },
76 {
77 label: t('menu.register'),
78 onClick: signUp,
79 id: 'SignUpTab',
80 },
81 {divider: true},
82 ];
83
84 const loggedMenuActions = [
85 {
86 label: t('menu.dashboard'),
87 onClick: goToDashboard,
88 id: 'GoToDashboardTab',
89 },
90 {
91 label: t('menu.profile'),
92 onClick: goProfile,
93 id: 'ProfileTab',
94 },
95 {divider: true},
96 ];
97
98 const menuActions = token ? loggedMenuActions : noUserMenuActions;
99 const userInfos = user
100 ? [{label: user.username, id: 'Email'}, {divider: true}]
101 : [];
102
103 const appLink = user ? '/dashboard' : `/e/${event.uuid}` || '';
104
105 const UserIcon = user ? (
106 <Avatar className={classes.avatar}>
107 {`${user.username[0]}`.toUpperCase()}
108 </Avatar>
109 ) : (
110 <Icon>more_vert</Icon>
111 );
112
113 return (
114 <AppBar
115 className={classes.appbar}
116 position="fixed"
117 color="primary"
118 id={
119 (isEditing && 'EditEvent') || (areDetailsOpened && 'Details') || 'Menu'
120 }
121 >
122 <Banner
123 message={announcement}
124 open={showAnnouncement}
125 onClear={onBannerClear}
126 />
127 <Toolbar>
128 <div className={classes.name}>
129 <Link href={appLink}>
130 <img
131 className={classes.logo}
132 src="/assets/Logo_in_beta.svg"
133 alt="Logo"
134 />
135 </Link>
136 <Tooltip title={event.name}>
137 <Typography
138 variant="h6"
139 noWrap
140 id="MenuHeaderTitle"
141 className={classes.title}
142 >
143 {event.name}
144 </Typography>
145 </Tooltip>
146
147 {areDetailsOpened && (
148 <IconButton
149 className="tour_event_edit"
150 color="inherit"
151 edge="end"
152 id="HeaderAction"
153 onClick={isEditing ? onSave : () => setIsEditing(true)}
154 >
155 <Icon>{isEditing ? 'done' : 'edit'}</Icon>
156 </IconButton>
157 )}
158 </div>
159 {areDetailsOpened ? (
160 <IconButton
161 color="inherit"
162 edge="end"
163 id="CloseDetailsBtn"
164 onClick={() => {
165 setIsEditing(false);
166 setAreDetailsOpened(!areDetailsOpened);
167 }}
168 >
169 <Icon>close</Icon>
170 </IconButton>
171 ) : (
172 <>
173 <IconButton
174 className={classes.shareIcon}
175 color="inherit"
176 edge="end"
177 id="ShareBtn"
178 onClick={() => setAreDetailsOpened(!areDetailsOpened)}
179 >
180 <Icon>share</Icon>
181 </IconButton>
182 <IconButton
183 className={clsx(classes.iconButtons, 'tour_event_infos')}
184 color="inherit"
185 edge="end"
186 id="ShareBtn"
187 onClick={() => setAreDetailsOpened(!areDetailsOpened)}
188 >
189 <Icon>information_outline</Icon>
190 </IconButton>
191 <IconButton
192 color="inherit"
193 edge="end"
194 id="MenuMoreInfo"
195 onClick={e => setAnchorEl(e.currentTarget)}
196 >
197 {UserIcon}
198 </IconButton>
199 </>
200 )}
201 {!areDetailsOpened && (
202 <GenericMenu
203 anchorEl={anchorEl}
204 setAnchorEl={setAnchorEl}
205 actions={[
206 ...userInfos,
207 ...[
208 {
209 label: areDetailsOpened
210 ? t('event.actions.hide_details')
211 : t('event.actions.show_details'),
212 onClick: e => {
213 setAnchorEl(null);
214 setAreDetailsOpened(!areDetailsOpened);
215 },
216 id: 'DetailsTab',
217 },
218 ],
219 ...menuActions,
220 ]}
221 />
222 )}
223 </Toolbar>
224 {areDetailsOpened && <EventDetails />}
225 </AppBar>
226 );
227};
228
229const useStyles = makeStyles(theme => ({
230 appbar: ({detailsOpen, bannerOffset, bannerHeight}) => ({
231 overflow: 'hidden',
232 minHeight: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
233 overflowY: detailsOpen ? 'scroll' : 'hidden',
234 transition: 'height 0.3s ease',
235 marginTop: bannerOffset - bannerHeight,
236 }),
237 logo: {
238 marginRight: theme.spacing(2),
239 width: 64,
240 height: 32,
241 cursor: 'pointer',
242 },
243 name: {
244 flexGrow: 1,
245 display: 'flex',
246 alignItems: 'center',
247 },
248 title: {
249 maxWidth: `calc(100vw - ${theme.spacing(30)}px)`,
250 },
251 iconButtons: {
252 margin: theme.spacing(0),
253 },
254 avatar: {
255 width: theme.spacing(3),
256 height: theme.spacing(3),
257 fontSize: 16,
258 },
259 shareIcon: {
260 marginRight: 0,
261 },
262}));
263
264export default EventBar;