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;