all repos — caroster @ 010e7c4c0be09d2510ffab44ec663174a79d5192

[Octree] Group carpool to your event https://caroster.io

app/src/containers/Car/HeaderEditing.js (view raw)

  1import React, {useState, useReducer, useCallback, useEffect} from 'react';
  2import Typography from '@material-ui/core/Typography';
  3import IconButton from '@material-ui/core/IconButton';
  4import Icon from '@material-ui/core/Icon';
  5import Button from '@material-ui/core/Button';
  6import moment from 'moment';
  7import {makeStyles} from '@material-ui/core/styles';
  8import {DateTimePicker} from '@material-ui/pickers';
  9import {useTranslation} from 'react-i18next';
 10import TextField from '@material-ui/core/TextField';
 11import Slider from '@material-ui/core/Slider';
 12import {useStrapi} from 'strapi-react-context';
 13import {useToast} from '../../contexts/Toast';
 14import {useEvent} from '../../contexts/Event';
 15import RemoveDialog from '../RemoveDialog';
 16
 17const HeaderEditing = ({car, toggleEditing}) => {
 18  const classes = useStyles();
 19  const {t} = useTranslation();
 20  const strapi = useStrapi();
 21  const {event} = useEvent();
 22  const {addToast} = useToast();
 23  const [removing, toggleRemoving] = useReducer(i => !i, false);
 24
 25  // States
 26  const [name, setName] = useState(car?.name ?? '');
 27  const [seats, setSeats] = useState(car?.seats ?? 4);
 28  const [meeting, setMeeting] = useState(car?.meeting ?? '');
 29  const [date, setDate] = useState(
 30    car?.departure ? moment(car.departure) : moment()
 31  );
 32  const [phone, setPhone] = useState(car?.phone_number ?? '');
 33  const [details, setDetails] = useState(car?.details ?? '');
 34
 35  // Click on ESQ should close the form
 36  const escFunction = useCallback(
 37    evt => {
 38      if (evt.keyCode === 27) toggleEditing();
 39    },
 40    [toggleEditing]
 41  );
 42
 43  useEffect(() => {
 44    document.addEventListener('keydown', escFunction, false);
 45    return () => {
 46      document.removeEventListener('keydown', escFunction, false);
 47    };
 48  }, [escFunction]);
 49
 50  const onSave = async evt => {
 51    if (evt.preventDefault) evt.preventDefault();
 52    try {
 53      // If new seats count is under current passengers count, put excedent in event waiting list
 54      if (!!car.passengers && car.passengers.length > seats) {
 55        const lostPassengers = car.passengers.slice(seats);
 56        if (lostPassengers.length > 0)
 57          await strapi.services.events.update(event.id, {
 58            waiting_list: [...(event.waiting_list ?? []), ...lostPassengers],
 59          });
 60      }
 61      // Update car
 62      await strapi.services.cars.update(car.id, {
 63        name,
 64        seats,
 65        meeting,
 66        departure: date.toISOString(),
 67        phone_number: phone,
 68        details,
 69        passengers: car.passengers ? car.passengers.slice(0, seats) : [],
 70      });
 71      toggleEditing();
 72    } catch (error) {
 73      console.error(error);
 74      addToast('car.errors.cant_update');
 75    }
 76    return false;
 77  };
 78
 79  const onRemove = async () => {
 80    try {
 81      // Put passengers in event waiting list (if any)
 82      if (Array.isArray(car?.passengers) && car.passengers.length > 0)
 83        await strapi.services.events.update(event.id, {
 84          waiting_list: [...(event.waiting_list ?? []), ...car.passengers],
 85        });
 86      // Remove car
 87      await strapi.services.cars.remove(car.id);
 88      addToast(t('car.actions.removed'));
 89      toggleEditing();
 90    } catch (error) {
 91      console.error(error);
 92      addToast('car.errors.cant_remove');
 93    }
 94  };
 95
 96  return (
 97    <div className={classes.header}>
 98      <form onSubmit={onSave}>
 99        <IconButton type="submit" className={classes.editBtn}>
100          <Icon>done</Icon>
101        </IconButton>
102        <DateTimePicker
103          label={t('event.creation.date')}
104          value={date}
105          onChange={setDate}
106          className={classes.textField}
107          fullWidth
108          format="LLLL"
109          disablePast
110          id="EditCarDateTime"
111          name="date"
112        />
113        <TextField
114          className={classes.textField}
115          label={t('car.creation.name')}
116          fullWidth
117          autoFocus
118          margin="dense"
119          value={name}
120          onChange={e => setName(e.target.value)}
121          id="EditCarName"
122          name="name"
123        />
124        <TextField
125          className={classes.textField}
126          label={t('car.creation.phone')}
127          fullWidth
128          autoFocus
129          margin="dense"
130          value={phone}
131          onChange={e => setPhone(e.target.value)}
132          id="EditCarPhone"
133          name="phone"
134        />
135        <TextField
136          className={classes.textField}
137          label={t('car.creation.meeting')}
138          fullWidth
139          margin="dense"
140          multiline
141          rows={2}
142          value={meeting}
143          onChange={e => setMeeting(e.target.value)}
144          id="EditCarMeeting"
145          name="meeting"
146        />
147        <TextField
148          className={classes.textField}
149          label={t('car.creation.notes')}
150          fullWidth
151          margin="dense"
152          multiline
153          rows={2}
154          value={details}
155          onChange={e => setDetails(e.target.value)}
156          id="EditCarDetails"
157          name="details"
158        />
159        <div className={classes.slider}>
160          <Typography variant="caption">{t('car.creation.seats')}</Typography>
161          <Slider
162            value={seats}
163            onChange={(e, value) => setSeats(value)}
164            step={1}
165            marks={[1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
166              value,
167              label: value,
168            }))}
169            min={1}
170            max={8}
171            valueLabelDisplay="auto"
172            id="EditCarSeats"
173          />
174        </div>
175      </form>
176      <div className={classes.actions}>
177        <Button
178          color="secondary"
179          variant="outlined"
180          onClick={toggleRemoving}
181          id="CarRemove"
182        >
183          {t('car.actions.remove')}
184        </Button>
185      </div>
186      <RemoveDialog
187        text={t('car.actions.remove_alert')}
188        open={removing}
189        onClose={toggleRemoving}
190        onRemove={onRemove}
191      />
192    </div>
193  );
194};
195
196const useStyles = makeStyles(theme => ({
197  header: {padding: theme.spacing(2)},
198  editBtn: {
199    position: 'absolute',
200    top: 0,
201    right: 0,
202    zIndex: theme.zIndex.speedDial,
203  },
204  section: {
205    marginTop: theme.spacing(2),
206  },
207  slider: {
208    marginTop: theme.spacing(2),
209  },
210  actions: {
211    display: 'flex',
212    justifyContent: 'center',
213    margin: theme.spacing(2, 0),
214  },
215}));
216
217export default HeaderEditing;