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 EventMenu from '../EventMenu';
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.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 <EventMenu
181 anchorEl={anchorEl}
182 setAnchorEl={setAnchorEl}
183 actions={[
184 ...userInfos,
185 ...[
186 {
187 label: detailsOpen
188 ? t('event.actions.hide_details')
189 : t('event.actions.show_details'),
190 onClick: toggleDetails,
191 id: 'DetailsTab',
192 },
193 ],
194 ...menuActions,
195 ]}
196 />
197 </Toolbar>
198 {detailsOpen && (
199 <EventDetails toggleDetails={toggleDetails} onShare={onShare} />
200 )}
201 </AppBar>
202 );
203};
204
205const onTourChange = (toggleDetails: Function) => {
206 const {prev, step, isCreator} = useTourStore.getState();
207 const fromTo = (step1: number, step2: number) =>
208 prev === step1 && step === step2;
209
210 if (isCreator) {
211 if (fromTo(1, 0) || fromTo(0, 1) || fromTo(3, 2) || fromTo(2, 3))
212 toggleDetails();
213 } else if (fromTo(2, 3) || fromTo(3, 2)) toggleDetails();
214};
215
216const useStyles = makeStyles(theme => ({
217 appbar: ({detailsOpen}) => ({
218 overflow: 'hidden',
219 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
220 overflowY: detailsOpen ? 'scroll' : 'hidden',
221 transition: 'height 0.3s ease',
222 zIndex: theme.zIndex.appBar,
223 position: 'fixed',
224 top: 0,
225 }),
226 logo: {
227 marginRight: theme.spacing(2),
228 width: 32,
229 height: 32,
230 cursor: 'pointer',
231 },
232 name: {
233 flexGrow: 1,
234 display: 'flex',
235 alignItems: 'center',
236 },
237 iconButtons: {
238 margin: theme.spacing(0),
239 },
240 avatar: {
241 width: theme.spacing(3),
242 height: theme.spacing(3),
243 fontSize: 16,
244 },
245 withDivider: {
246 borderBottom: `1px solid ${theme.palette.divider}`,
247 },
248}));
249
250export default EventBar;