all repos — caroster @ 909da40dfacac3dc44510c641077653dfe6e7709

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