all repos — caroster @ 5e8d53baf4f6676069cef7da12605ec9ae0375ed

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

frontend/containers/TravelColumns/index.tsx (view raw)

  1import {useEffect, useReducer, useRef, useState} from 'react';
  2import {makeStyles} from '@material-ui/core/styles';
  3import Container from '@material-ui/core/Container';
  4import Slider from 'react-slick';
  5import {Travel as TravelType} from '../../generated/graphql';
  6import useEventStore from '../../stores/useEventStore';
  7import useTourStore from '../../stores/useTourStore';
  8import {
  9  AddPassengerToTravel,
 10  AddPassengerToWaitingList,
 11} from '../NewPassengerDialog';
 12import WaitingList from '../WaitingList';
 13import Travel from '../Travel';
 14import AddTravel from './AddTravel';
 15import sliderSettings from './_SliderSettings';
 16
 17interface Props {
 18  toggleNewTravel: () => void;
 19}
 20
 21const TravelColumns = (props: Props) => {
 22  const event = useEventStore(s => s.event);
 23  const {travels = []} = event || {};
 24  const slider = useRef(null);
 25  const tourStep = useTourStore(s => s.step);
 26  const classes = useStyles();
 27  const [newPassengerTravel, toggleNewPassengerToTravel] = useState<TravelType | null>(null);
 28  const [openNewPassengerToWaitingList, toggleNewPassengerToWaitingList] =
 29    useReducer(i => !i, false);
 30
 31  // On tour step changes : component update
 32  useEffect(() => {
 33    onTourChange(slider.current);
 34  }, [tourStep]);
 35
 36  return (
 37    <div className={classes.container}>
 38      <div className={classes.dots} id="slider-dots" />
 39      <div className={classes.slider}>
 40        <Slider ref={slider} {...sliderSettings}>
 41          <Container maxWidth="sm" className={classes.slide}>
 42            <WaitingList toggleNewPassenger={toggleNewPassengerToWaitingList} />
 43          </Container>
 44          {travels
 45            ?.slice()
 46            .sort(sortTravels)
 47            .map(travel => (
 48              <Container
 49                key={travel.id}
 50                maxWidth="sm"
 51                className={classes.slide}
 52              >
 53                <Travel
 54                  travel={travel}
 55                  {...props}
 56                  toggleNewPassenger={() =>
 57                    toggleNewPassengerToTravel(travel)
 58                  }
 59                />
 60              </Container>
 61            ))}
 62          <Container maxWidth="sm" className={classes.slide}>
 63            <AddTravel {...props} />
 64          </Container>
 65        </Slider>
 66      </div>
 67      {!!newPassengerTravel && (
 68        <AddPassengerToTravel
 69          travel={newPassengerTravel}
 70          open={!!newPassengerTravel}
 71          toggle={() => toggleNewPassengerToTravel(null)}
 72        />
 73      )}
 74      <AddPassengerToWaitingList
 75        open={openNewPassengerToWaitingList}
 76        toggle={toggleNewPassengerToWaitingList}
 77      />
 78    </div>
 79  );
 80};
 81
 82const onTourChange = slider => {
 83  const {prev, step, isCreator} = useTourStore.getState();
 84  const fromTo = (step1: number, step2: number) =>
 85    prev === step1 && step === step2;
 86
 87  if (isCreator) {
 88    if (fromTo(2, 3) || fromTo(4, 3)) slider?.slickGoTo(0, true);
 89  } else if (fromTo(0, 1)) slider?.slickGoTo(0, true);
 90};
 91
 92const sortTravels = (a: TravelType, b: TravelType) => {
 93  if (!b) return 1;
 94  const dateA = new Date(a.departure).getTime();
 95  const dateB = new Date(b.departure).getTime();
 96  if (dateA === dateB)
 97    return new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
 98  else return dateA - dateB;
 99};
100
101const useStyles = makeStyles(theme => ({
102  container: {
103    minHeight: '100vh',
104    paddingTop: theme.mixins.toolbar.minHeight,
105    paddingLeft: theme.spacing(6),
106    paddingRight: theme.spacing(6),
107    [theme.breakpoints.down('sm')]: {
108      paddingLeft: theme.spacing(),
109      paddingRight: theme.spacing(),
110    },
111    display: 'flex',
112    flexDirection: 'column',
113    overflowX: 'hidden',
114    overflowY: 'auto',
115  },
116  dots: {
117    height: 32,
118    overflow: 'auto',
119    '& overflow': '-moz-scrollbars-none',
120    '-ms-overflow-style': 'none',
121    '&::-webkit-scrollbar': {
122      height: '0 !important',
123    },
124    '& .slick-dots': {
125      position: 'static',
126      '& li': {
127        display: 'block',
128      },
129    },
130    '& .slick-dots li:first-child button:before, & .slick-dots li:last-child button:before':
131      {
132        color: theme.palette.primary.main,
133      },
134  },
135  slider: {
136    flexGrow: 1,
137    height: 1,
138    '& .slick-slider': {
139      height: '100%',
140      '& .slick-list': {
141        overflow: 'visible',
142      },
143      cursor: 'grab',
144    },
145  },
146  slide: {
147    padding: theme.spacing(1),
148    marginBottom: theme.spacing(12),
149    outline: 'none',
150    '& > *': {
151      cursor: 'default',
152    },
153  },
154}));
155
156export default TravelColumns;