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