all repos — caroster @ 49a93ce3c1bfd93f18ce02b24fa4b04ce954ee79

[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          autoFocus
110        />
111        <TimePicker
112          label={t('travel.creation.time')}
113          slotProps={{
114            textField: {
115              sx: {width: '100%', pb: 2},
116            },
117          }}
118          value={time}
119          onChange={setTime}
120          ampm={false}
121          minutesStep={5}
122        />
123        <TextField
124          label={t('travel.creation.name')}
125          fullWidth
126          sx={{pb: 2}}
127          value={name}
128          onChange={e => setName(e.target.value)}
129          name="name"
130          id="EditTravelName"
131        />
132        <TextField
133          label={t('travel.creation.phone')}
134          fullWidth
135          sx={{pb: 2}}
136          value={phone}
137          onChange={e => setPhone(e.target.value)}
138          name="phone"
139          id="EditTravelPhone"
140        />
141        <PlaceInput
142          label={t('travel.creation.meeting')}
143          textFieldProps={{sx: {pb: 2}}}
144          place={meeting}
145          latitude={meeting_latitude}
146          longitude={meeting_longitude}
147          onSelect={({place, latitude, longitude}) => {
148            setMeeting(place);
149            setMeetingLatitude(latitude);
150            setMeetingLongitude(longitude);
151          }}
152        />
153        <TextField
154          label={t('travel.creation.notes')}
155          fullWidth
156          sx={{pb: 2}}
157          multiline
158          maxRows={4}
159          inputProps={{maxLength: 250}}
160          helperText={`${details.length}/250`}
161          value={details}
162          onChange={e => setDetails(e.target.value)}
163          name="details"
164          id="EditTravelDetails"
165        />
166        <Box sx={{marginTop: theme.spacing(2)}}>
167          <Typography variant="caption">
168            {t('travel.creation.seats')}
169          </Typography>
170          <Slider
171            value={seats}
172            onChange={(e, value) => setSeats(value)}
173            step={1}
174            marks={[1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
175              value,
176              label: value,
177            }))}
178            min={1}
179            max={8}
180            valueLabelDisplay="auto"
181            id="EditTravelSeats"
182          />
183        </Box>
184      </form>
185      <Box
186        sx={{
187          display: 'flex',
188          flexDirection: 'column',
189          justifyContent: 'center',
190          margin: theme.spacing(2, 0),
191          '& > *:first-child': {
192            marginBottom: theme.spacing(2),
193          },
194        }}
195      >
196        <Button
197          variant="contained"
198          color="primary"
199          onClick={onSave}
200          id="TravelSave"
201        >
202          {t('generic.save')}
203        </Button>
204        <Button
205          variant="outlined"
206          color="primary"
207          onClick={toggleRemoving}
208          id="TravelRemove"
209        >
210          {t('generic.remove')}
211        </Button>
212      </Box>
213      <RemoveDialog
214        text={
215          isCarosterPlus
216            ? t`travel.actions.remove_alert.caroster_plus`
217            : t`travel.actions.remove_alert`
218        }
219        open={removing}
220        onClose={toggleRemoving}
221        onRemove={onRemove}
222      />
223    </Box>
224  );
225};
226
227export default HeaderEditing;