all repos — caroster @ v0.9.0

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