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 window.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 !!token && {
172 label: t('event.actions.logout'),
173 onClick: logout,
174 id: 'LogoutTab',
175 },
176 ].filter(Boolean)}
177 />
178 </Toolbar>
179 <Container className={classes.container} maxWidth="sm">
180 <EventDetails toggleDetails={toggleDetails} />
181 </Container>
182 </AppBar>
183 <CarColumns toggleNewCar={toggleNewCar} />
184 <EventFab toggleNewCar={toggleNewCar} open={openNewCar} />
185 <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
186 <AddToMyEventDialog
187 open={isAddToMyEvent}
188 onClose={() => setIsAddToMyEvent(false)}
189 event={event}
190 />
191 </Layout>
192 );
193};
194
195const useStyles = makeStyles(theme => ({
196 container: {
197 padding: theme.spacing(2),
198 },
199 appbar: ({detailsOpen}) => ({
200 overflow: 'hidden',
201 height: detailsOpen ? '100vh' : theme.mixins.toolbar.minHeight,
202 transition: 'height 0.3s ease',
203 zIndex: theme.zIndex.appBar,
204 position: 'fixed',
205 top: 0,
206 }),
207 name: {
208 flexGrow: 1,
209 display: 'flex',
210 alignItems: 'center',
211 },
212 shareIcon: {
213 marginRight: theme.spacing(0),
214 },
215}));
216
217const EventWithContext = props => (
218 <EventProvider {...props}>
219 <Event {...props} />
220 </EventProvider>
221);
222export default EventWithContext;