all repos — caroster @ 3cce17ca690426c1c205c1239652172d5e83e9fb

[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  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;