all repos — caroster @ e5c55de093d4edc0ba99de71ea4ce6b32179268a

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