all repos — caroster @ d2e47634bff1fe498b6b81f90a89ff0b5817c5c8

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

frontend/layouts/Event.tsx (view raw)

  1import {PropsWithChildren, useEffect, useState} from 'react';
  2import useMediaQuery from '@material-ui/core/useMediaQuery';
  3import {makeStyles, useTheme} from '@material-ui/core/styles';
  4import {useTranslation} from 'react-i18next';
  5import ErrorPage from '../pages/_error';
  6import useEventStore from '../stores/useEventStore';
  7import Layout from '../layouts/Default';
  8import EventBar from '../containers/EventBar';
  9import {
 10  Event as EventType,
 11  useEventByUuidQuery,
 12  useUpdateEventMutation,
 13  EditEventInput,
 14} from '../generated/graphql';
 15import DrawerMenu from '../containers/DrawerMenu';
 16import AddToMyEventDialog from '../containers/AddToMyEventDialog';
 17import useToastStore from '../stores/useToastStore';
 18import Box from '@material-ui/core/Box';
 19
 20const POLL_INTERVAL = 10000;
 21
 22export type TabComponent = (props: {event: EventType}) => JSX.Element;
 23
 24interface Props {
 25  eventUUID: string;
 26  Tab: TabComponent;
 27}
 28
 29const EventLayout = (props: PropsWithChildren<Props>) => {
 30  const {eventUUID, Tab} = props;
 31  const {t} = useTranslation();
 32  const theme = useTheme();
 33  const classes = useStyles();
 34  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
 35  const addToast = useToastStore(s => s.addToast);
 36  const setEvent = useEventStore(s => s.setEvent);
 37  const eventUpdate = useEventStore(s => s.event);
 38  const setIsEditing = useEventStore(s => s.setIsEditing);
 39  const [updateEvent] = useUpdateEventMutation();
 40  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 41  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 42    pollInterval: POLL_INTERVAL,
 43    variables: {uuid: eventUUID},
 44  });
 45
 46  useEffect(() => {
 47    if (event) setEvent(event as EventType);
 48  }, [event]);
 49
 50  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 51
 52  const onSave = async e => {
 53    try {
 54      const {uuid, ...data} = eventUpdate;
 55      const {id, __typename, travels, users, waitingList, ...input} = data;
 56      await updateEvent({
 57        variables: {uuid, eventUpdate: input as EditEventInput},
 58        refetchQueries: ['eventByUUID'],
 59      });
 60      setIsEditing(false);
 61    } catch (error) {
 62      console.error(error);
 63      addToast(t('event.errors.cant_update'));
 64    }
 65  };
 66
 67  return (
 68    <Layout
 69      pageTitle={t('event.title', {title: event.name})}
 70      menuTitle={t('event.title', {title: event.name})}
 71      displayMenu={false}
 72      Topbar={() => (
 73        <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} />
 74      )}
 75    >
 76      <Box
 77        flex={1}
 78        display="flex"
 79        alignItems="stretch"
 80        flexDirection={isMobile ? 'column-reverse' : 'row'}
 81      >
 82        <DrawerMenu />
 83        <Box className={classes.content}>
 84          <Tab event={event} />
 85        </Box>
 86      </Box>
 87      <AddToMyEventDialog
 88        event={event}
 89        open={isAddToMyEvent}
 90        onClose={() => setIsAddToMyEvent(false)}
 91      />
 92    </Layout>
 93  );
 94};
 95
 96const useStyles = makeStyles(theme => ({
 97  content: {
 98    flex: 1,
 99    maxWidth: 'calc(100% - 85px)',
100
101    [theme.breakpoints.down('sm')]: {
102      maxWidth: '100%',
103    },
104  },
105}));
106
107export default EventLayout;