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: () => {
77 setAnchorEl(null);
78 onTourRestart();
79 },
80 id: 'TourTab',
81 },
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 label: t('menu.tour'),
98 onClick: () => {
99 setAnchorEl(null);
100 onTourRestart();
101 },
102 id: 'TourTab',
103 },
104 ];
105
106 const menuActions = token ? loggedMenuActions : noUserMenuActions;
107 const userInfos = user
108 ? [{label: user.username, id: 'Email'}, {divider: true}]
109 : [];
110
111 const UserIcon = user ? (
112 <Avatar className={classes.avatar}>
113 {`${user.username[0]}`.toUpperCase()}
114 </Avatar>
115 ) : (
116 <Icon>more_vert</Icon>
117 );
118
119 return (
120 <AppBar
121 className={classes.appbar}
122 position="static"
123 color="primary"
124 id={(isEditing && 'EditEvent') || (detailsOpen && 'Details') || 'Menu'}
125 >
126 <Toolbar>
127 <div className={classes.name}>
128 <Link href={settings?.['about_link'] || ''}>
129 <img
130 className={classes.logo}
131 src="/assets/Logo_in_beta.svg"
132 alt="Logo"
133 />
134 </Link>
135 <Typography variant="h6" noWrap id="MenuHeaderTitle">
136 {event.name}
137 </Typography>
138 {detailsOpen && (
139 <IconButton
140 className="tour_event_edit"
141 color="inherit"
142 edge="end"
143 id="HeaderAction"
144 onClick={isEditing ? onSave : () => setIsEditing(true)}
145 >
146 <Icon>{isEditing ? 'done' : 'edit'}</Icon>
147 </IconButton>
148 )}
149 </div>
150 {detailsOpen ? (
151 <IconButton
152 color="inherit"
153 edge="end"
154 id="CloseDetailsBtn"
155 onClick={() => {
156 setIsEditing(false);
157 toggleDetails();
158 }}
159 >
160 <Icon>close</Icon>
161 </IconButton>
162 ) : (
163 <>
164 <IconButton
165 className={classes.shareIcon}
166 color="inherit"
167 edge="end"
168 id="ShareBtn"
169 onClick={toggleDetails}
170 >
171 <Icon>share</Icon>
172 </IconButton>
173 <IconButton
174 className={clsx(classes.iconButtons, 'tour_event_infos')}
175 color="inherit"
176 edge="end"
177 id="ShareBtn"
178 onClick={toggleDetails}
179 >
180 <Icon>information_outline</Icon>
181 </IconButton>
182 <IconButton
183 color="inherit"
184 edge="end"
185 id="MenuMoreInfo"
186 onClick={e => setAnchorEl(e.currentTarget)}
187 >
188 {UserIcon}
189 </IconButton>
190 </>
191 )}
192 {!detailsOpen && (
193 <GenericMenu
194 anchorEl={anchorEl}
195 setAnchorEl={setAnchorEl}
196 actions={[
197 ...userInfos,
198 ...[
199 {
200 label: detailsOpen
201 ? t('event.actions.hide_details')
202 : t('event.actions.show_details'),
203 onClick: e => {
204 setAnchorEl(null);
205 toggleDetails();
206 },
207 id: 'DetailsTab',
208 },
209 ],
210 ...menuActions,
211 ]}
212 />
213 )}
214 </Toolbar>
215 {detailsOpen && (
216 <EventDetails toggleDetails={toggleDetails} onShare={onShare} />
217 )}
218 </AppBar>
219 );
220};
221
222const onTourChange = (toggleDetails: Function) => {
223 const {prev, step, isCreator} = useTourStore.getState();
224 const fromTo = (step1: number, step2: number) =>
225 prev === step1 && step === step2;
226
227 if (isCreator) {
228 if (fromTo(1, 0) || fromTo(0, 1) || fromTo(3, 2) || fromTo(2, 3))
229 toggleDetails();
230 } else if (fromTo(2, 3) || fromTo(3, 2)) toggleDetails();
231};
232
233const useStyles = makeStyles(theme => ({
234 appbar: ({detailsOpen}) => ({
235 overflow: 'hidden',
236 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
237 overflowY: detailsOpen ? 'scroll' : 'hidden',
238 transition: 'height 0.3s ease',
239 zIndex: theme.zIndex.appBar,
240 position: 'fixed',
241 top: 0,
242 }),
243 logo: {
244 marginRight: theme.spacing(2),
245 width: 64,
246 height: 32,
247 cursor: 'pointer',
248 },
249 name: {
250 flexGrow: 1,
251 display: 'flex',
252 alignItems: 'center',
253 },
254 iconButtons: {
255 margin: theme.spacing(0),
256 },
257 avatar: {
258 width: theme.spacing(3),
259 height: theme.spacing(3),
260 fontSize: 16,
261 },
262 shareIcon: {
263 marginRight: 0,
264 },
265}));
266
267export default EventBar;