all repos — caroster @ ea414277b269eb8ba96835769f2e44ca1069f093

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

frontend/containers/NewTravelDialog/index.tsx (view raw)

  1import {useState, forwardRef, useMemo, useEffect} from 'react';
  2import {makeStyles} from '@material-ui/core/styles';
  3import Dialog from '@material-ui/core/Dialog';
  4import DialogActions from '@material-ui/core/DialogActions';
  5import DialogContent from '@material-ui/core/DialogContent';
  6import DialogTitle from '@material-ui/core/DialogTitle';
  7import Button from '@material-ui/core/Button';
  8import Slide from '@material-ui/core/Slide';
  9import TextField from '@material-ui/core/TextField';
 10import Slider from '@material-ui/core/Slider';
 11import Typography from '@material-ui/core/Typography';
 12import {DatePicker, TimePicker} from '@material-ui/pickers';
 13import moment, {Moment} from 'moment';
 14import {useTranslation} from 'react-i18next';
 15import useEventStore from '../../stores/useEventStore';
 16import useActions from './useActions';
 17import {Vehicle} from '../../generated/graphql';
 18
 19interface Props {
 20  context: {
 21    vehicle: Vehicle;
 22    opened: boolean;
 23  };
 24  toggle: ({opened: boolean}) => void;
 25}
 26
 27const NewTravelDialog = ({context, toggle}: Props) => {
 28  const {t} = useTranslation();
 29  const classes = useStyles();
 30  const event = useEventStore(s => s.event);
 31  const {createTravel} = useActions({event});
 32
 33  const dateMoment = useMemo(() => {
 34    if (!event?.date) return moment();
 35    else return moment(event.date);
 36  }, [event?.date]);
 37
 38  // States
 39  const [name, setName] = useState('');
 40  const [seats, setSeats] = useState(4);
 41  const [meeting, setMeeting] = useState('');
 42  const [date, setDate] = useState(dateMoment);
 43  const [time, setTime] = useState(dateMoment);
 44  const [phone, setPhone] = useState('');
 45  const [details, setDetails] = useState('');
 46  const canCreate = !!name && !!seats;
 47
 48  useEffect(() => {
 49    if (context.vehicle) {
 50      setName(context.vehicle.name);
 51      setSeats(context.vehicle.seats);
 52      setPhone(context.vehicle.phone_number);
 53    }
 54  }, [context.vehicle]);
 55
 56  const onCreate = async e => {
 57    if (e.preventDefault) e.preventDefault();
 58
 59    const travel = {
 60      meeting,
 61      details,
 62      seats,
 63      vehicleName: name,
 64      phone_number: phone,
 65      departure: formatDate(date, time),
 66      event: event.id,
 67    };
 68    const createVehicle = !context.vehicle;
 69
 70    await createTravel({...travel, createVehicle});
 71    toggle({opened: false});
 72
 73    // Clear states
 74    setName('');
 75    setSeats(4);
 76    setMeeting('');
 77    setDate(moment());
 78    setPhone('');
 79    setDetails('');
 80  };
 81
 82  return (
 83    <Dialog
 84      fullWidth
 85      maxWidth="xs"
 86      open={context?.opened}
 87      onClose={() => toggle({opened: false})}
 88      TransitionComponent={Transition}
 89    >
 90      <form onSubmit={onCreate}>
 91        <DialogTitle>{t('travel.creation.title')}</DialogTitle>
 92        <DialogContent>
 93          <DatePicker
 94            label={t('travel.creation.date')}
 95            fullWidth
 96            helperText=" "
 97            value={date}
 98            onChange={setDate}
 99            format="DD/MM/YYYY"
100            cancelLabel={t('generic.cancel')}
101            autoFocus
102            id="NewTravelDateTime"
103          />
104          <TimePicker
105            label={t('travel.creation.time')}
106            fullWidth
107            helperText=" "
108            value={time}
109            onChange={setTime}
110            cancelLabel={t('generic.cancel')}
111            ampm={false}
112            minutesStep={5}
113            id="NewTravelTime"
114          />
115          <TextField
116            label={t('travel.creation.name')}
117            fullWidth
118            helperText=" "
119            value={name}
120            onChange={e => setName(e.target.value)}
121            name="name"
122            id="NewTravelName"
123          />
124          <TextField
125            label={t('travel.creation.phone')}
126            fullWidth
127            helperText=" "
128            value={phone}
129            onChange={e => setPhone(e.target.value)}
130            name="phone"
131            id="NewTravelPhone"
132          />
133          <TextField
134            label={t('travel.creation.meeting')}
135            fullWidth
136            multiline
137            rowsMax={4}
138            inputProps={{maxLength: 250}}
139            helperText={`${meeting.length}/250`}
140            value={meeting}
141            onChange={e => setMeeting(e.target.value)}
142            name="meeting"
143            id="NewTravelMeeting"
144          />
145          <TextField
146            label={t('travel.creation.notes')}
147            fullWidth
148            multiline
149            rowsMax={4}
150            inputProps={{maxLength: 250}}
151            helperText={`${details.length}/250`}
152            value={details}
153            onChange={e => setDetails(e.target.value)}
154            name="details"
155            id="NewTravelDetails"
156          />
157          <div className={classes.slider}>
158            <Typography variant="caption">
159              {t('travel.creation.seats')}
160            </Typography>
161            <Slider
162              value={seats}
163              onChange={(e, value) => setSeats(value)}
164              step={1}
165              marks={MARKS}
166              min={1}
167              max={MARKS.length}
168              valueLabelDisplay="auto"
169              id="NewTravelSeats"
170            />
171          </div>
172        </DialogContent>
173        <DialogActions>
174          <Button
175            color="primary"
176            id="NewTravelCancel"
177            onClick={() => toggle({opened: false})}
178            tabIndex={-1}
179          >
180            {t('generic.cancel')}
181          </Button>
182          <Button
183            color="primary"
184            variant="contained"
185            type="submit"
186            disabled={!canCreate}
187            aria-disabled={!canCreate}
188            id="NewTravelSubmit"
189          >
190            {t('generic.create')}
191          </Button>
192        </DialogActions>
193      </form>
194    </Dialog>
195  );
196};
197
198const Transition = forwardRef(function Transition(props, ref) {
199  return <Slide direction="up" ref={ref} {...props} />;
200});
201
202const formatDate = (date: Moment, time: Moment) => {
203  return moment(
204    `${moment(date).format('YYYY-MM-DD')} ${moment(time).format('HH:mm')}`,
205    'YYYY-MM-DD HH:mm'
206  ).toISOString();
207};
208
209const MARKS = [1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
210  value,
211  label: value,
212}));
213
214const useStyles = makeStyles(theme => ({
215  slider: {
216    marginTop: theme.spacing(2),
217  },
218}));
219
220export default NewTravelDialog;