all repos — caroster @ 65bcb7d208677b65df7ba31f656ee6ee0cfb1d1d

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