frontend/containers/WaitingList/TravelDialog.tsx (view raw)
1import moment from 'moment';
2import Link from '@material-ui/core/Link';
3import Typography from '@material-ui/core/Typography';
4import Button from '@material-ui/core/Button';
5import Slide from '@material-ui/core/Slide';
6import Dialog from '@material-ui/core/Dialog';
7import AppBar from '@material-ui/core/AppBar';
8import Toolbar from '@material-ui/core/Toolbar';
9import ListItem from '@material-ui/core/ListItem';
10import List from '@material-ui/core/List';
11import IconButton from '@material-ui/core/IconButton';
12import Icon from '@material-ui/core/Icon';
13import Box from '@material-ui/core/Box';
14import {makeStyles} from '@material-ui/core/styles';
15import {useTranslation} from 'react-i18next';
16import {forwardRef} from 'react';
17import getMapsLink from '../../utils/getMapsLink';
18import ShareEvent from '../ShareEvent';
19import {Passenger, TravelEntity, Travel} from '../../generated/graphql';
20
21interface Props {
22 eventName: string;
23 travels: Array<TravelEntity>;
24 passenger: Passenger;
25 open: boolean;
26 onClose: () => void;
27 onSelect: (travel: Travel & {id: string}) => void;
28}
29
30const TravelDialog = ({
31 eventName,
32 travels,
33 passenger,
34 open,
35 onClose,
36 onSelect,
37}: Props) => {
38 const classes = useStyles();
39 const {t} = useTranslation();
40
41 const availableTravels = travels?.filter(
42 ({attributes}) =>
43 attributes.passengers &&
44 attributes?.seats > attributes.passengers.data.length
45 );
46
47 return (
48 <Dialog
49 fullScreen
50 open={open}
51 onClose={onClose}
52 TransitionComponent={Transition}
53 >
54 <AppBar>
55 <Toolbar>
56 <IconButton onClick={onClose} color="inherit">
57 <Icon>arrow_back_ios</Icon>
58 </IconButton>
59 <Typography variant="h5">
60 {t('passenger.creation.available_cars')}
61 </Typography>
62 </Toolbar>
63 </AppBar>
64 {(availableTravels.length === 0 && (
65 <Box className={classes.noTravel}>
66 <Typography variant="h5">
67 {t('passenger.creation.no_travel.title')}
68 </Typography>
69 <img className={classes.noTravelImage} src="/assets/car.png" />
70 <Typography>
71 {t('passenger.creation.no_travel.desc', {name: passenger?.name})}
72 </Typography>
73 <ShareEvent
74 color="primary"
75 className={classes.share}
76 title={`Caroster ${eventName}`}
77 url={`${typeof window !== 'undefined' ? window.location.href : ''}`}
78 />
79 </Box>
80 )) || (
81 <div className={classes.offset}>
82 <List disablePadding>
83 {availableTravels.map(({id, attributes}, i) => {
84 const travel = {id, ...attributes};
85 const passengersCount = travel?.passengers?.data.length || 0;
86 const counter = `${passengersCount} / ${travel?.seats || 0}`;
87 return (
88 <ListItem key={i} divider className={classes.listItem}>
89 <Box className={classes.rtlBox}>
90 <Box className={classes.info}>
91 <Typography variant="subtitle1" className={classes.date}>
92 {t('passenger.creation.departure')}
93 {moment(travel.departure).format('LLLL')}
94 </Typography>
95 <Link
96 target="_blank"
97 rel="noreferrer"
98 href={getMapsLink(travel.meeting)}
99 onClick={e => e.preventDefault}
100 >
101 {travel.meeting}
102 </Link>
103 </Box>
104 <Box className={classes.info}>
105 <Typography variant="h6">{travel.vehicleName}</Typography>
106 <Typography variant="body2">
107 {t('passenger.creation.seats', {seats: counter})}
108 </Typography>
109 </Box>
110 </Box>
111 <Button
112 color="primary"
113 variant="contained"
114 onClick={() => onSelect(travel)}
115 className={classes.button}
116 >
117 {t('passenger.creation.assign')}
118 </Button>
119 </ListItem>
120 );
121 })}
122 </List>
123 </div>
124 )}
125 </Dialog>
126 );
127};
128
129const Transition = forwardRef(function Transition(props, ref) {
130 return <Slide direction="up" ref={ref} {...props} />;
131});
132
133const useStyles = makeStyles(theme => ({
134 offset: {
135 paddingTop: theme.spacing(7),
136 },
137 rtlBox: {
138 display: 'flex',
139 padding: 0,
140 margin: 0,
141 direction: 'rtl',
142 [theme.breakpoints.down('sm')]: {
143 display: 'block',
144 paddingBottom: theme.spacing(1),
145 },
146 },
147 info: {
148 padding: theme.spacing(0, 4, 0, 0),
149 width: '350px',
150 [theme.breakpoints.down('sm')]: {
151 padding: theme.spacing(0.5, 1),
152 width: '100%',
153 textAlign: 'left',
154 },
155 },
156 listItem: {
157 display: 'flex',
158 justifyContent: 'left',
159 [theme.breakpoints.down('sm')]: {
160 display: 'block',
161 textAlign: 'center',
162 },
163 },
164 date: {
165 textTransform: 'capitalize',
166 padding: theme.spacing(0, 0, 0.5, 0),
167 },
168 button: {
169 padding: theme.spacing(1, 15),
170 margin: theme.spacing(1),
171 },
172 noTravel: {
173 margin: '120px auto 0 auto',
174 width: '330px',
175 maxWidth: '100%',
176 textAlign: 'center',
177 },
178 noTravelImage: {
179 width: 'calc(100% - 2px)',
180 [theme.breakpoints.down('sm')]: {
181 width: 'calc(50% - 2px)',
182 },
183 },
184 share: {
185 marginTop: theme.spacing(2),
186 backgroundColor: '#fff',
187 },
188}));
189
190export default TravelDialog;