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;