frontend/containers/NewCarDialog/index.tsx (view raw)
1import {useState, forwardRef, useMemo} from 'react';
2import {makeStyles} from '@material-ui/core/styles';
3import Dialog from '@material-ui/core/Dialog';
4import DialogActions from '@material-ui/core/DialogActions';
5import DialogContent from '@material-ui/core/DialogContent';
6import DialogTitle from '@material-ui/core/DialogTitle';
7import Button from '@material-ui/core/Button';
8import Slide from '@material-ui/core/Slide';
9import TextField from '@material-ui/core/TextField';
10import Slider from '@material-ui/core/Slider';
11import Typography from '@material-ui/core/Typography';
12import {DatePicker, TimePicker} from '@material-ui/pickers';
13import moment from 'moment';
14import {useTranslation} from 'react-i18next';
15import useEventStore from '../../stores/useEventStore';
16import useToastsStore from '../../stores/useToastStore';
17import useAddToEvents from '../../hooks/useAddToEvents';
18import {useCreateCarMutation} from '../../generated/graphql';
19
20const NewCarDialog = ({open, toggle}) => {
21 const {t} = useTranslation();
22 const classes = useStyles();
23 const addToast = useToastsStore(s => s.addToast);
24 const {addToEvent} = useAddToEvents();
25 const event = useEventStore(s => s.event);
26 const [createCar] = useCreateCarMutation({refetchQueries: ['eventByUUID']});
27 const dateMoment = useMemo(() => {
28 if (!event?.date) return moment();
29 else return moment(event.date);
30 }, [event?.date]);
31
32 // States
33 const [name, setName] = useState('');
34 const [seats, setSeats] = useState(4);
35 const [meeting, setMeeting] = useState('');
36 const [date, setDate] = useState(dateMoment);
37 const [time, setTime] = useState(dateMoment);
38 const [phone, setPhone] = useState('');
39 const [details, setDetails] = useState('');
40 const canCreate = !!name && !!seats;
41
42 const onCreate = async e => {
43 if (e.preventDefault) e.preventDefault();
44 try {
45 const departure = moment(
46 `${moment(date).format('YYYY-MM-DD')} ${moment(time).format('HH:mm')}`,
47 'YYYY-MM-DD HH:mm'
48 ).toISOString();
49 await createCar({
50 variables: {
51 car: {
52 name,
53 seats,
54 meeting,
55 departure,
56 phone_number: phone,
57 details,
58 event: event.id,
59 },
60 },
61 });
62 addToEvent(event.id);
63 addToast(t('car.creation.created'));
64 toggle();
65
66 // Clear states
67 setName('');
68 setSeats(4);
69 setMeeting('');
70 setDate(moment());
71 setPhone('');
72 setDetails('');
73 } catch (error) {
74 console.error(error);
75 addToast(t('car.errors.cant_create'));
76 }
77 return false;
78 };
79
80 return (
81 <Dialog
82 fullWidth
83 maxWidth="sm"
84 open={open}
85 onClose={toggle}
86 TransitionComponent={Transition}
87 >
88 <form onSubmit={onCreate}>
89 <DialogTitle>{t('car.creation.title')}</DialogTitle>
90 <DialogContent>
91 <TextField
92 label={t('car.creation.name')}
93 value={name}
94 onChange={e => setName(e.target.value)}
95 fullWidth
96 autoFocus
97 id="NewCarName"
98 name="name"
99 />
100 <DatePicker
101 id="NewCarDateTime"
102 className={classes.picker}
103 fullWidth
104 label={t('car.creation.date')}
105 format="DD/MM/YYYY"
106 value={date}
107 onChange={setDate}
108 />
109 <TimePicker
110 id="NewCarTime"
111 className={classes.picker}
112 fullWidth
113 label={t('car.creation.time')}
114 value={time}
115 onChange={setTime}
116 ampm={false}
117 minutesStep={5}
118 />
119 <Typography variant="caption">{t('car.creation.seats')}</Typography>
120 <Slider
121 value={seats}
122 onChange={(e, value) => setSeats(value)}
123 step={1}
124 min={1}
125 max={MARKS.length}
126 marks={MARKS}
127 valueLabelDisplay="auto"
128 />
129 <TextField
130 label={t('car.creation.meeting')}
131 value={meeting}
132 onChange={e => setMeeting(e.target.value)}
133 fullWidth
134 margin="dense"
135 id="NewCarMeeting"
136 name="meeting"
137 />
138 <TextField
139 label={t('car.creation.phone')}
140 value={phone}
141 onChange={e => setPhone(e.target.value)}
142 fullWidth
143 margin="dense"
144 id="NewCarPhone"
145 name="phone"
146 />
147 <TextField
148 label={t('car.creation.notes')}
149 value={details}
150 onChange={e => setDetails(e.target.value)}
151 fullWidth
152 margin="dense"
153 inputProps={{maxLength: 250}}
154 helperText={`${details.length}/250`}
155 multiline
156 rows={4}
157 id="NewCarDetails"
158 name="details"
159 />
160 </DialogContent>
161 <DialogActions>
162 <Button
163 color="primary"
164 id="NewCarCancel"
165 onClick={toggle}
166 tabIndex={-1}
167 >
168 {t('generic.cancel')}
169 </Button>
170 <Button
171 color="primary"
172 variant="contained"
173 type="submit"
174 disabled={!canCreate}
175 aria-disabled={!canCreate}
176 id="NewCarSubmit"
177 >
178 {t('generic.create')}
179 </Button>
180 </DialogActions>
181 </form>
182 </Dialog>
183 );
184};
185
186const Transition = forwardRef(function Transition(props, ref) {
187 return <Slide direction="up" ref={ref} {...props} />;
188});
189
190const MARKS = [1, 2, 3, 4, 5, 6, 7, 8].map(value => ({
191 value,
192 label: value,
193}));
194
195const useStyles = makeStyles(theme => ({
196 picker: {
197 marginTop: theme.spacing(3),
198 marginBottom: theme.spacing(3),
199 },
200}));
201
202export default NewCarDialog;