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