all repos — caroster @ 41eb7416d94d282b03f56d6a18017671ed515a57

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

frontend/containers/Travel/HeaderEditing.tsx (view raw)

  1import {useState, useReducer, useCallback, useEffect, useMemo} from 'react';
  2import Typography from '@mui/material/Typography';
  3import Button from '@mui/material/Button';
  4import TextField from '@mui/material/TextField';
  5import Slider from '@mui/material/Slider';
  6import moment, {Moment} from 'moment';
  7import {useTheme} from '@mui/material/styles';
  8import {DatePicker} from '@mui/x-date-pickers/DatePicker';
  9import {TimePicker} from '@mui/x-date-pickers/TimePicker';
 10import {useTranslation} from 'react-i18next';
 11import RemoveDialog from '../RemoveDialog';
 12import useActions from './useActions';
 13import Box from '@mui/material/Box';
 14import PlaceInput from '../PlaceInput';
 15
 16const HeaderEditing = ({travel, toggleEditing}) => {
 17  const {t} = useTranslation();
 18  const theme = useTheme();
 19  const actions = useActions({travel});
 20  const [removing, toggleRemoving] = useReducer(i => !i, false);
 21  const dateMoment = useMemo(
 22    () => (travel?.departure ? moment(travel.departure) : null),
 23    [travel?.departure]
 24  );
 25
 26  // States
 27  const [name, setName] = useState(travel?.vehicleName ?? '');
 28  const [seats, setSeats] = useState(travel?.seats ?? 4);
 29  const [meeting, setMeeting] = useState(travel?.meeting ?? '');
 30  const [meeting_latitude, setMeetingLatitude] = useState(null);
 31  const [meeting_longitude, setMeetingLongitude] = useState(null);
 32  const [date, setDate] = useState(dateMoment);
 33  const [time, setTime] = useState(dateMoment);
 34  const [phone, setPhone] = useState(travel?.phone_number ?? '');
 35  const [details, setDetails] = useState(travel?.details ?? '');
 36
 37  // Click on ESQ closes the form
 38  const escFunction = useCallback(
 39    evt => {
 40      if (evt.keyCode === 27) toggleEditing();
 41    },
 42    [toggleEditing]
 43  );
 44
 45  useEffect(() => {
 46    document.addEventListener('keydown', escFunction, false);
 47    return () => {
 48      document.removeEventListener('keydown', escFunction, false);
 49    };
 50  }, [escFunction]);
 51
 52  const onSave = async event => {
 53    if (event.preventDefault) event.preventDefault();
 54    const travelUpdate = {
 55      meeting,
 56      meeting_latitude,
 57      meeting_longitude,
 58      details,
 59      seats,
 60      phone_number: phone,
 61      vehicleName: name,
 62      departure: formatDate(date, time),
 63    };
 64    await actions.updateTravel(travelUpdate);
 65    toggleEditing();
 66  };
 67
 68  const onRemove = async () => {
 69    await actions.removeTravel();
 70    toggleEditing();
 71  };
 72
 73  return (
 74    <Box sx={{padding: 2}}>
 75      <form onSubmit={onSave}>
 76        <DatePicker
 77          slotProps={{
 78            textField: {
 79              sx: {width: '100%', pb: 2},
 80            },
 81          }}
 82          format="DD/MM/YYYY"
 83          label={t('travel.creation.date')}
 84          value={date}
 85          onChange={setDate}
 86          autoFocus
 87        />
 88        <TimePicker
 89          label={t('travel.creation.time')}
 90          slotProps={{
 91            textField: {
 92              sx: {width: '100%', pb: 2},
 93            },
 94          }}
 95          value={time}
 96          onChange={setTime}
 97          ampm={false}
 98          minutesStep={5}
 99        />
100        <TextField
101          label={t('travel.creation.name')}
102          fullWidth
103          sx={{pb: 2}}
104          value={name}
105          onChange={e => setName(e.target.value)}
106          name="name"
107          id="EditTravelName"
108        />
109        <TextField
110          label={t('travel.creation.phone')}
111          fullWidth
112          sx={{pb: 2}}
113          value={phone}
114          onChange={e => setPhone(e.target.value)}
115          name="phone"
116          id="EditTravelPhone"
117        />
118        <PlaceInput
119          label={t('travel.creation.meeting')}
120          textFieldProps={{sx: {pb: 2}}}
121          place={meeting}
122          latitude={meeting_latitude}
123          longitude={meeting_longitude}
124          onSelect={({place, latitude, longitude}) => {
125            setMeeting(place);
126            setMeetingLatitude(latitude);
127            setMeetingLongitude(longitude);
128          }}
129        />
130        <TextField
131          label={t('travel.creation.notes')}
132          fullWidth
133          sx={{pb: 2}}
134          multiline
135          maxRows={4}
136          inputProps={{maxLength: 250}}
137          helperText={`${details.length}/250`}
138          value={details}
139          onChange={e => setDetails(e.target.value)}
140          name="details"
141          id="EditTravelDetails"
142        />
143        <Box sx={{marginTop: theme.spacing(2)}}>
144          <Typography variant="caption">
145            {t('travel.creation.seats')}
146          </Typography>
147          <Slider
148            value={seats}
149            onChange={(e, value) => setSeats(value)}
150            step={1}
151            marks={[1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
152              value,
153              label: value,
154            }))}
155            min={1}
156            max={8}
157            valueLabelDisplay="auto"
158            id="EditTravelSeats"
159          />
160        </Box>
161      </form>
162      <Box
163        sx={{
164          display: 'flex',
165          flexDirection: 'column',
166          justifyContent: 'center',
167          margin: theme.spacing(2, 0),
168          '& > *:first-child': {
169            marginBottom: theme.spacing(2),
170          },
171        }}
172      >
173        <Button
174          variant="contained"
175          color="primary"
176          onClick={onSave}
177          id="TravelSave"
178        >
179          {t('generic.save')}
180        </Button>
181        <Button
182          variant="outlined"
183          color="primary"
184          onClick={toggleRemoving}
185          id="TravelRemove"
186        >
187          {t('generic.remove')}
188        </Button>
189      </Box>
190      <RemoveDialog
191        text={t('travel.actions.remove_alert')}
192        open={removing}
193        onClose={toggleRemoving}
194        onRemove={onRemove}
195      />
196    </Box>
197  );
198};
199
200const formatDate = (date: Moment, time: Moment) => {
201  return moment(
202    `${moment(date).format('YYYY-MM-DD')} ${moment(time).format('HH:mm')}`,
203    'YYYY-MM-DD HH:mm'
204  ).toISOString();
205};
206
207export default HeaderEditing;