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