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