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 {useAuth} from 'strapi-react-context';
5import AppBar from '@material-ui/core/AppBar';
6import Toolbar from '@material-ui/core/Toolbar';
7import Container from '@material-ui/core/Container';
8import Typography from '@material-ui/core/Typography';
9import IconButton from '@material-ui/core/IconButton';
10import Icon from '@material-ui/core/Icon';
11import {makeStyles} from '@material-ui/core/styles';
12import {useEvent, EventProvider} from '../contexts/Event';
13import {useToast} from '../contexts/Toast';
14import Layout from '../layouts/Default';
15import Loading from './Loading';
16import EventMenu from '../containers/EventMenu';
17import EventDetails from '../containers/EventDetails';
18import Fab from '../containers/Fab';
19import CarColumns from '../containers/CarColumns';
20import NewCarDialog from '../containers/NewCarDialog';
21import AddToMyEventDialog from '../containers/AddToMyEventDialog';
22import {useHistory} from 'react-router-dom';
23
24const Event = () => {
25 const {t} = useTranslation();
26 const history = useHistory();
27 const {addToast} = useToast();
28 const [anchorEl, setAnchorEl] = useState(null);
29 const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
30 const [detailsOpen, toggleDetails] = useReducer(i => !i, false);
31 const classes = useStyles({detailsOpen});
32 const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
33 const {event, isEditing, setIsEditing, updateEvent} = useEvent();
34 const {token} = useAuth();
35 useEffect(() => {
36 window.scrollTo(0, 0);
37 }, []);
38
39 useEffect(() => {
40 if (!detailsOpen) setIsEditing(false);
41 }, [detailsOpen]); // eslint-disable-line react-hooks/exhaustive-deps
42
43 const onEventSave = async e => {
44 try {
45 await updateEvent();
46 setIsEditing(false);
47 } catch (error) {
48 console.error(error);
49 addToast(t('event.errors.cant_update'));
50 }
51 };
52
53 const onShare = async () => {
54 if (!event) return null;
55 // If navigator as share capability
56 if (!!navigator.share)
57 return await navigator.share({
58 title: `Caroster ${event.name}`,
59 url: `${window.location.href}`,
60 });
61 // Else copy URL in clipboard
62 else if (!!navigator.clipboard) {
63 await navigator.clipboard.writeText(window.location.href);
64 addToast(t('event.actions.copied'));
65 return true;
66 }
67 };
68
69 const addToMyEvents = () => {
70 if (!event) return;
71 window.localStorage.setItem('addToMyEvents', event.id);
72 setIsAddToMyEvent(true);
73 };
74
75 const signUp = () => {
76 if (!event) return;
77 history.push({
78 pathname: '/register',
79 state: {event: event.id},
80 });
81 };
82
83 const signIn = history.push.bind(undefined, '/login');
84 const goToDashboard = history.push.bind(undefined, '/dashboard');
85 const goProfile = history.push.bind(undefined, '/profile');
86 const goAbout = () => (window.location.href = t('meta.about_href'));
87
88 if (!event) return <Loading />;
89
90 return (
91 <Layout>
92 <Helmet>
93 <title>{t('meta.title', {title: event.name})}</title>
94 </Helmet>
95 <AppBar
96 position="static"
97 color="primary"
98 className={classes.appbar}
99 id={(isEditing && 'EditEvent') || (detailsOpen && 'Details') || 'Menu'}
100 >
101 <Toolbar>
102 <div className={classes.name}>
103 <Typography variant="h6" noWrap id="MenuHeaderTitle">
104 {event.name}
105 </Typography>
106 {detailsOpen && !isEditing && (
107 <IconButton
108 color="inherit"
109 edge="end"
110 id="CloseDetailsBtn"
111 onClick={() => setIsEditing(true)}
112 >
113 <Icon>edit</Icon>
114 </IconButton>
115 )}
116 {detailsOpen && isEditing && (
117 <IconButton
118 color="inherit"
119 edge="end"
120 id="EditEventSubmit"
121 onClick={onEventSave}
122 >
123 <Icon>done</Icon>
124 </IconButton>
125 )}
126 </div>
127 {!detailsOpen && (
128 <>
129 <IconButton
130 color="inherit"
131 edge="end"
132 id="ShareBtn"
133 onClick={onShare}
134 className={classes.shareIcon}
135 >
136 <Icon>share</Icon>
137 </IconButton>
138 <IconButton
139 color="inherit"
140 edge="end"
141 id="MenuMoreInfo"
142 onClick={e => setAnchorEl(e.currentTarget)}
143 >
144 <Icon>more_vert</Icon>
145 </IconButton>
146 </>
147 )}
148 {detailsOpen && (
149 <IconButton
150 color="inherit"
151 edge="end"
152 id="CloseDetailsBtn"
153 onClick={() => {
154 setIsEditing(false);
155 toggleDetails();
156 }}
157 >
158 <Icon>close</Icon>
159 </IconButton>
160 )}
161 <EventMenu
162 anchorEl={anchorEl}
163 setAnchorEl={setAnchorEl}
164 actions={[
165 {
166 label: detailsOpen
167 ? t('event.actions.hide_details')
168 : t('event.actions.show_details'),
169 onClick: toggleDetails,
170 id: 'DetailsTab',
171 },
172 !token && {
173 label: t('event.actions.add_to_my_events'),
174 onClick: addToMyEvents,
175 id: 'AddToMyEventsTab',
176 },
177 !!token && {
178 label: t('menu.dashboard'),
179 onClick: goToDashboard,
180 id: 'GoToDashboardTab',
181 },
182 !token && {
183 label: t('menu.login'),
184 onClick: signIn,
185 id: 'SignInTab',
186 },
187 !token && {
188 label: t('menu.register'),
189 onClick: signUp,
190 id: 'SignUpTab',
191 },
192 !!token && {
193 label: t('menu.profile'),
194 onClick: goProfile,
195 id: 'ProfileTab',
196 },
197 {
198 label: t('menu.about'),
199 onClick: goAbout,
200 id: 'AboutTab',
201 },
202 ].filter(Boolean)}
203 />
204 </Toolbar>
205 {detailsOpen && (
206 <Container className={classes.container} maxWidth="sm">
207 <EventDetails toggleDetails={toggleDetails} />
208 </Container>
209 )}
210 </AppBar>
211 <CarColumns toggleNewCar={toggleNewCar} />
212 <Fab onClick={toggleNewCar} open={openNewCar} aria-label="add-car" />
213 <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
214 <AddToMyEventDialog
215 open={isAddToMyEvent}
216 onClose={() => setIsAddToMyEvent(false)}
217 event={event}
218 />
219 </Layout>
220 );
221};
222
223const useStyles = makeStyles(theme => ({
224 container: {
225 padding: theme.spacing(2),
226 },
227 appbar: ({detailsOpen}) => ({
228 overflow: 'hidden',
229 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
230 overflowY: detailsOpen ? 'scroll' : 'hidden',
231 transition: 'height 0.3s ease',
232 zIndex: theme.zIndex.appBar,
233 position: 'fixed',
234 top: 0,
235 }),
236 name: {
237 flexGrow: 1,
238 display: 'flex',
239 alignItems: 'center',
240 },
241 shareIcon: {
242 marginRight: theme.spacing(0),
243 },
244}));
245
246const EventWithContext = props => (
247 <EventProvider {...props}>
248 <Event {...props} />
249 </EventProvider>
250);
251export default EventWithContext;