all repos — caroster @ e5e05d4f020e8e0eff917468ce530cdbc16f7e40

[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 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  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        <GenericMenu
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  shareIcon: {
246    marginRight: 0,
247  },
248}));
249
250export default EventBar;