all repos — caroster @ 1936e259c0f6d0ba58363becc5fd98c8391b826e

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

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 '../../lib/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;