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