app/src/pages/Event.js (view raw)
1import React, {useState, useReducer, useEffect} from 'react';
2import {Helmet} from 'react-helmet';
3import {useTranslation} from 'react-i18next';
4import AppBar from '@material-ui/core/AppBar';
5import Toolbar from '@material-ui/core/Toolbar';
6import Container from '@material-ui/core/Container';
7import Typography from '@material-ui/core/Typography';
8import IconButton from '@material-ui/core/IconButton';
9import Icon from '@material-ui/core/Icon';
10import {makeStyles} from '@material-ui/core/styles';
11import {useEvent, EventProvider} from '../contexts/Event';
12import {useToast} from '../contexts/Toast';
13import Layout from '../layouts/Default';
14import Loading from '../pages/Loading';
15import EventMenu from '../containers/EventMenu';
16import EventDetails from '../containers/EventDetails';
17import EventFab from '../containers/EventFab';
18import CarColumns from '../containers/CarColumns';
19import NewCarDialog from '../containers/NewCarDialog';
20
21const Event = () => {
22 const {t} = useTranslation();
23 const {addToast} = useToast();
24 const [anchorEl, setAnchorEl] = useState(null);
25 const [detailsOpen, toggleDetails] = useReducer(i => !i, false);
26 const classes = useStyles({detailsOpen});
27 const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
28 const {event, isEditing, setIsEditing, updateEvent} = useEvent();
29
30 useEffect(() => {
31 window.scrollTo(0, 0);
32 }, []);
33
34 useEffect(() => {
35 if (!detailsOpen) setIsEditing(false);
36 }, [detailsOpen]); // eslint-disable-line react-hooks/exhaustive-deps
37
38 const onEventSave = async e => {
39 try {
40 await updateEvent();
41 setIsEditing(false);
42 } catch (error) {
43 console.error(error);
44 addToast(t('event.errors.cant_update'));
45 }
46 };
47
48 const onShare = async () => {
49 if (!event) return null;
50 // If navigator as share capability
51 if (!!navigator.share)
52 return await navigator.share({
53 title: `Caroster ${event.name}`,
54 url: `${window.location.href}`,
55 });
56 // Else copy URL in clipboard
57 else if (!!navigator.clipboard) {
58 await navigator.clipboard.writeText(window.location.href);
59 addToast(t('event.actions.copied'));
60 return true;
61 }
62 };
63
64 if (!event) return <Loading />;
65
66 return (
67 <Layout>
68 <Helmet>
69 <title>{t('meta.title', {title: event.name})}</title>
70 </Helmet>
71 <AppBar
72 position="static"
73 color="primary"
74 className={classes.appbar}
75 id={(isEditing && 'EditEvent') || (detailsOpen && 'Details') || 'Menu'}
76 >
77 <Toolbar>
78 <div className={classes.name}>
79 <Typography variant="h6" noWrap id="MenuHeaderTitle">
80 {event.name}
81 </Typography>
82 {detailsOpen && !isEditing && (
83 <IconButton
84 color="inherit"
85 edge="end"
86 id="CloseDetailsBtn"
87 onClick={() => setIsEditing(true)}
88 >
89 <Icon>edit</Icon>
90 </IconButton>
91 )}
92 {detailsOpen && isEditing && (
93 <IconButton
94 color="inherit"
95 edge="end"
96 id="EditEventSubmit"
97 onClick={onEventSave}
98 >
99 <Icon>done</Icon>
100 </IconButton>
101 )}
102 </div>
103 {!detailsOpen && (
104 <>
105 <IconButton
106 color="inherit"
107 edge="end"
108 id="ShareBtn"
109 onClick={onShare}
110 className={classes.shareIcon}
111 >
112 <Icon>share</Icon>
113 </IconButton>
114 <IconButton
115 color="inherit"
116 edge="end"
117 id="MenuMoreInfo"
118 onClick={e => setAnchorEl(e.currentTarget)}
119 >
120 <Icon>more_vert</Icon>
121 </IconButton>
122 </>
123 )}
124 {detailsOpen && (
125 <IconButton
126 color="inherit"
127 edge="end"
128 id="CloseDetailsBtn"
129 onClick={() => {
130 setIsEditing(false);
131 toggleDetails();
132 }}
133 >
134 <Icon>close</Icon>
135 </IconButton>
136 )}
137 <EventMenu
138 anchorEl={anchorEl}
139 setAnchorEl={setAnchorEl}
140 actions={[
141 {
142 label: detailsOpen
143 ? t('event.actions.hide_details')
144 : t('event.actions.show_details'),
145 onClick: toggleDetails,
146 id: 'DetailsTab',
147 },
148 {
149 label: t('event.actions.add_car'),
150 onClick: toggleNewCar,
151 id: 'NewCarTab',
152 },
153 {
154 label: t('event.actions.invite'),
155 onClick: () => {},
156 id: 'InviteTab',
157 },
158 ]}
159 />
160 </Toolbar>
161 <Container className={classes.container} maxWidth="sm">
162 <EventDetails toggleDetails={toggleDetails} />
163 </Container>
164 </AppBar>
165 <CarColumns toggleNewCar={toggleNewCar} />
166 <EventFab toggleNewCar={toggleNewCar} open={openNewCar} />
167 <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
168 </Layout>
169 );
170};
171
172const useStyles = makeStyles(theme => ({
173 container: {
174 padding: theme.spacing(2),
175 },
176 appbar: ({detailsOpen}) => ({
177 overflow: 'hidden',
178 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
179 transition: 'height 0.3s ease',
180 zIndex: theme.zIndex.appBar,
181 position: 'fixed',
182 top: 0,
183 }),
184 name: {
185 flexGrow: 1,
186 display: 'flex',
187 alignItems: 'center',
188 },
189 shareIcon: {
190 marginRight: theme.spacing(0),
191 },
192}));
193
194const EventWithContext = props => (
195 <EventProvider {...props}>
196 <Event {...props} />
197 </EventProvider>
198);
199export default EventWithContext;