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 '../pages/Loading';
16import EventMenu from '../containers/EventMenu';
17import EventDetails from '../containers/EventDetails';
18import EventFab from '../containers/EventFab';
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
87 if (!event) return <Loading />;
88
89 return (
90 <Layout>
91 <Helmet>
92 <title>{t('meta.title', {title: event.name})}</title>
93 </Helmet>
94 <AppBar
95 position="static"
96 color="primary"
97 className={classes.appbar}
98 id={(isEditing && 'EditEvent') || (detailsOpen && 'Details') || 'Menu'}
99 >
100 <Toolbar>
101 <div className={classes.name}>
102 <Typography variant="h6" noWrap id="MenuHeaderTitle">
103 {event.name}
104 </Typography>
105 {detailsOpen && !isEditing && (
106 <IconButton
107 color="inherit"
108 edge="end"
109 id="CloseDetailsBtn"
110 onClick={() => setIsEditing(true)}
111 >
112 <Icon>edit</Icon>
113 </IconButton>
114 )}
115 {detailsOpen && isEditing && (
116 <IconButton
117 color="inherit"
118 edge="end"
119 id="EditEventSubmit"
120 onClick={onEventSave}
121 >
122 <Icon>done</Icon>
123 </IconButton>
124 )}
125 </div>
126 {!detailsOpen && (
127 <>
128 <IconButton
129 color="inherit"
130 edge="end"
131 id="ShareBtn"
132 onClick={onShare}
133 className={classes.shareIcon}
134 >
135 <Icon>share</Icon>
136 </IconButton>
137 <IconButton
138 color="inherit"
139 edge="end"
140 id="MenuMoreInfo"
141 onClick={e => setAnchorEl(e.currentTarget)}
142 >
143 <Icon>more_vert</Icon>
144 </IconButton>
145 </>
146 )}
147 {detailsOpen && (
148 <IconButton
149 color="inherit"
150 edge="end"
151 id="CloseDetailsBtn"
152 onClick={() => {
153 setIsEditing(false);
154 toggleDetails();
155 }}
156 >
157 <Icon>close</Icon>
158 </IconButton>
159 )}
160 <EventMenu
161 anchorEl={anchorEl}
162 setAnchorEl={setAnchorEl}
163 actions={[
164 {
165 label: detailsOpen
166 ? t('event.actions.hide_details')
167 : t('event.actions.show_details'),
168 onClick: toggleDetails,
169 id: 'DetailsTab',
170 },
171 !token && {
172 label: t('event.actions.add_to_my_events'),
173 onClick: addToMyEvents,
174 id: 'AddToMyEventsTab',
175 },
176 !!token && {
177 label: t('event.actions.my_events'),
178 onClick: goToDashboard,
179 id: 'GoToDashboardTab',
180 },
181 !token && {
182 label: t('event.actions.signin'),
183 onClick: signIn,
184 id: 'SignInTab',
185 },
186 !token && {
187 label: t('event.actions.signup'),
188 onClick: signUp,
189 id: 'SignUpTab',
190 },
191 !!token && {
192 label: t('event.actions.my_profile'),
193 onClick: goProfile,
194 id: 'ProfileTab',
195 },
196 ].filter(Boolean)}
197 />
198 </Toolbar>
199 <Container className={classes.container} maxWidth="sm">
200 <EventDetails toggleDetails={toggleDetails} />
201 </Container>
202 </AppBar>
203 <CarColumns toggleNewCar={toggleNewCar} />
204 <EventFab toggleNewCar={toggleNewCar} open={openNewCar} />
205 <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
206 <AddToMyEventDialog
207 open={isAddToMyEvent}
208 onClose={() => setIsAddToMyEvent(false)}
209 event={event}
210 />
211 </Layout>
212 );
213};
214
215const useStyles = makeStyles(theme => ({
216 container: {
217 padding: theme.spacing(2),
218 },
219 appbar: ({detailsOpen}) => ({
220 overflow: 'hidden',
221 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
222 transition: 'height 0.3s ease',
223 zIndex: theme.zIndex.appBar,
224 position: 'fixed',
225 top: 0,
226 }),
227 name: {
228 flexGrow: 1,
229 display: 'flex',
230 alignItems: 'center',
231 },
232 shareIcon: {
233 marginRight: theme.spacing(0),
234 },
235}));
236
237const EventWithContext = props => (
238 <EventProvider {...props}>
239 <Event {...props} />
240 </EventProvider>
241);
242export default EventWithContext;