all repos — caroster @ fe359e3d0bd28293a74106f4ce391f5127bce55f

[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            onSelect={({location, place}) => {
123              setMeeting(place);
124              setMeetingLatitude(location[1]);
125              setMeetingLongitude(location[0]);
126            }}
127          />
128        <TextField
129          label={t('travel.creation.notes')}
130          fullWidth
131          sx={{pb: 2}}
132          multiline
133          maxRows={4}
134          inputProps={{maxLength: 250}}
135          helperText={`${details.length}/250`}
136          value={details}
137          onChange={e => setDetails(e.target.value)}
138          name="details"
139          id="EditTravelDetails"
140        />
141        <Box sx={{marginTop: theme.spacing(2)}}>
142          <Typography variant="caption">
143            {t('travel.creation.seats')}
144          </Typography>
145          <Slider
146            value={seats}
147            onChange={(e, value) => setSeats(value)}
148            step={1}
149            marks={[1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
150              value,
151              label: value,
152            }))}
153            min={1}
154            max={8}
155            valueLabelDisplay="auto"
156            id="EditTravelSeats"
157          />
158        </Box>
159      </form>
160      <Box
161        sx={{
162          display: 'flex',
163          flexDirection: 'column',
164          justifyContent: 'center',
165          margin: theme.spacing(2, 0),
166          '& > *:first-child': {
167            marginBottom: theme.spacing(2),
168          },
169        }}
170      >
171        <Button
172          variant="contained"
173          color="primary"
174          onClick={onSave}
175          id="TravelSave"
176        >
177          {t('generic.save')}
178        </Button>
179        <Button
180          variant="outlined"
181          color="primary"
182          onClick={toggleRemoving}
183          id="TravelRemove"
184        >
185          {t('generic.remove')}
186        </Button>
187      </Box>
188      <RemoveDialog
189        text={t('travel.actions.remove_alert')}
190        open={removing}
191        onClose={toggleRemoving}
192        onRemove={onRemove}
193      />
194    </Box>
195  );
196};
197
198const formatDate = (date: Moment, time: Moment) => {
199  return moment(
200    `${moment(date).format('YYYY-MM-DD')} ${moment(time).format('HH:mm')}`,
201    'YYYY-MM-DD HH:mm'
202  ).toISOString();
203};
204
205export default HeaderEditing;