all repos — caroster @ e6d45fde70b1f3324eb4275c885541f0d1346f21

[Octree] Group carpool to your event https://caroster.io

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