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