all repos — caroster @ d0d47704e427face6c4cea5a2e1326c3679f6f5d

[Octree] Group carpool to your event https://caroster.io

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