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