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