all repos — caroster @ d0d47704e427face6c4cea5a2e1326c3679f6f5d

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

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    [theme.breakpoints.down('sm')]: {
182      width: '50%',
183    },
184  },
185  share: {
186    marginTop: theme.spacing(2),
187  },
188}));
189
190export default TravelDialog;