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 {Event as EventType, useEventByUuidQuery} from '../generated/graphql';
10import DrawerMenu from '../containers/DrawerMenu';
11import AddToMyEventDialog from '../containers/AddToMyEventDialog';
12import Box from '@material-ui/core/Box';
13
14const POLL_INTERVAL = 10000;
15
16export type TabComponent = (props: {
17 event: EventType & {id: string};
18}) => JSX.Element;
19
20interface Props {
21 eventUUID: string;
22 Tab: TabComponent;
23}
24
25const EventLayout = (props: PropsWithChildren<Props>) => {
26 const {eventUUID, Tab, ...pageProps} = props;
27 const {t} = useTranslation();
28 const theme = useTheme();
29 const classes = useStyles();
30 const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
31 const setEvent = useEventStore(s => s.setEvent);
32 const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
33 const {data: {eventByUUID: {data: {attributes, id} = {}} = {}} = {}} =
34 useEventByUuidQuery({
35 pollInterval: POLL_INTERVAL,
36 variables: {uuid: eventUUID},
37 });
38 const event = {id, ...attributes};
39
40 useEffect(() => {
41 if (event) setEvent(event);
42 }, [event]);
43
44 if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
45
46 return (
47 <Layout
48 pageTitle={t('event.title', {title: event.name})}
49 menuTitle={t('event.title', {title: event.name})}
50 displayMenu={false}
51 Topbar={() => <EventBar event={event} onAdd={setIsAddToMyEvent} />}
52 {...pageProps}
53 >
54 <Box
55 flex={1}
56 display="flex"
57 alignItems="stretch"
58 height="calc(100% - 56px)"
59 overflow="hidden"
60 flexDirection={isMobile ? 'column-reverse' : 'row'}
61 >
62 <DrawerMenu />
63 <Box className={classes.content}>
64 <Tab event={event} />
65 </Box>
66 </Box>
67 <AddToMyEventDialog
68 event={event}
69 open={isAddToMyEvent}
70 onClose={() => setIsAddToMyEvent(false)}
71 />
72 </Layout>
73 );
74};
75
76const useStyles = makeStyles(theme => ({
77 content: {
78 flex: 1,
79 maxWidth: 'calc(100% - 85px)',
80 overflow: 'auto',
81 paddingBottom: theme.spacing(4),
82
83 [theme.breakpoints.down('sm')]: {
84 maxWidth: '100%',
85 },
86 },
87}));
88
89export default EventLayout;