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