all repos — caroster @ 832452704d5eae9e2164e58c086cdf365e51e5e7

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