all repos — caroster @ e7bfddaa0ab038f5a4aec786406badd9a85f2237

[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 ? 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          cancelLabel={t('generic.cancel')}
113        />
114        <TextField
115          className={classes.textField}
116          label={t('car.creation.name')}
117          fullWidth
118          autoFocus
119          margin="dense"
120          value={name}
121          onChange={e => setName(e.target.value)}
122          id="EditCarName"
123          name="name"
124        />
125        <TextField
126          className={classes.textField}
127          label={t('car.creation.phone')}
128          fullWidth
129          autoFocus
130          margin="dense"
131          value={phone}
132          onChange={e => setPhone(e.target.value)}
133          id="EditCarPhone"
134          name="phone"
135        />
136        <TextField
137          className={classes.textField}
138          label={t('car.creation.meeting')}
139          fullWidth
140          margin="dense"
141          multiline
142          rows={2}
143          value={meeting}
144          onChange={e => setMeeting(e.target.value)}
145          id="EditCarMeeting"
146          name="meeting"
147        />
148        <TextField
149          className={classes.textField}
150          label={t('car.creation.notes')}
151          fullWidth
152          margin="dense"
153          multiline
154          rows={2}
155          value={details}
156          onChange={e => setDetails(e.target.value)}
157          id="EditCarDetails"
158          name="details"
159        />
160        <div className={classes.slider}>
161          <Typography variant="caption">{t('car.creation.seats')}</Typography>
162          <Slider
163            value={seats}
164            onChange={(e, value) => setSeats(value)}
165            step={1}
166            marks={[1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
167              value,
168              label: value,
169            }))}
170            min={1}
171            max={8}
172            valueLabelDisplay="auto"
173            id="EditCarSeats"
174          />
175        </div>
176      </form>
177      <div className={classes.actions}>
178        <Button
179          variant="outlined"
180          color="primary"
181          onClick={toggleRemoving}
182          id="CarRemove"
183        >
184          {t('car.actions.remove')}
185        </Button>
186      </div>
187      <RemoveDialog
188        text={t('car.actions.remove_alert')}
189        open={removing}
190        onClose={toggleRemoving}
191        onRemove={onRemove}
192      />
193    </div>
194  );
195};
196
197const useStyles = makeStyles(theme => ({
198  header: {padding: theme.spacing(2)},
199  editBtn: {
200    position: 'absolute',
201    top: 0,
202    right: 0,
203    zIndex: theme.zIndex.speedDial,
204  },
205  section: {
206    marginTop: theme.spacing(2),
207  },
208  slider: {
209    marginTop: theme.spacing(2),
210  },
211  actions: {
212    display: 'flex',
213    justifyContent: 'center',
214    margin: theme.spacing(2, 0),
215  },
216}));
217
218export default HeaderEditing;