]> git.localhorst.tv Git - alttp.git/blob - resources/js/components/results/ReportForm.js
svg dungeon tracker
[alttp.git] / resources / js / components / results / ReportForm.js
1 import axios from 'axios';
2 import { withFormik } from 'formik';
3 import PropTypes from 'prop-types';
4 import React from 'react';
5 import { Button, Col, Form, Modal, Row } from 'react-bootstrap';
6 import { withTranslation } from 'react-i18next';
7 import toastr from 'toastr';
8
9 import LargeCheck from '../common/LargeCheck';
10 import laravelErrorsToFormik from '../../helpers/laravelErrorsToFormik';
11 import { findResult } from '../../helpers/User';
12 import { formatTime, parseTime } from '../../helpers/Result';
13 import i18n from '../../i18n';
14 import yup from '../../schema/yup';
15
16 const ReportForm = ({
17         errors,
18         handleBlur,
19         handleChange,
20         handleSubmit,
21         onCancel,
22         round,
23         touched,
24         values,
25 }) =>
26 <Form noValidate onSubmit={handleSubmit}>
27         <Modal.Body>
28                 {!round.locked ?
29                         <Row>
30                                 <Form.Group as={Col} sm={9} controlId="report.time">
31                                         <Form.Label>{i18n.t('results.reportTime')}</Form.Label>
32                                         <Form.Control
33                                                 isInvalid={!!(touched.time && errors.time)}
34                                                 name="time"
35                                                 onBlur={handleBlur}
36                                                 onChange={handleChange}
37                                                 placeholder={values.forfeit ? 'DNF' : '1:22:59'}
38                                                 type="text"
39                                                 value={values.time || ''}
40                                         />
41                                         {touched.time && errors.time ?
42                                                 <Form.Control.Feedback type="invalid">
43                                                         {i18n.t(errors.time)}
44                                                 </Form.Control.Feedback>
45                                         :
46                                                 <Form.Text muted>
47                                                         {parseTime(values.time) ?
48                                                                 i18n.t(
49                                                                         'results.reportPreview',
50                                                                         { time: formatTime({ time: parseTime(values.time) })},
51                                                                 )
52                                                         : null}
53                                                 </Form.Text>
54                                         }
55                                 </Form.Group>
56                                 <Form.Group as={Col} sm={3} controlId="report.forfeit">
57                                         <Form.Label>{i18n.t('results.forfeit')}</Form.Label>
58                                         <Form.Control
59                                                 as={LargeCheck}
60                                                 isInvalid={!!(touched.forfeit && errors.forfeit)}
61                                                 name="forfeit"
62                                                 onBlur={handleBlur}
63                                                 onChange={handleChange}
64                                                 value={!!values.forfeit}
65                                         />
66                                 </Form.Group>
67                         </Row>
68                 : null}
69                 <Form.Group controlId="report.vod">
70                         <Form.Label>{i18n.t('results.vod')}</Form.Label>
71                         <Form.Control
72                                 isInvalid={!!(touched.vod && errors.vod)}
73                                 name="vod"
74                                 onBlur={handleBlur}
75                                 onChange={handleChange}
76                                 placeholder="https://twitch.tv/youtube"
77                                 type="text"
78                                 value={values.vod || ''}
79                         />
80                         {touched.vod && errors.vod ?
81                                 <Form.Control.Feedback type="invalid">
82                                         {i18n.t(errors.vod)}
83                                 </Form.Control.Feedback>
84                         :
85                                 <Form.Text muted>
86                                         {i18n.t('results.vodNote')}
87                                 </Form.Text>
88                         }
89                 </Form.Group>
90                 <Form.Group controlId="report.comment">
91                         <Form.Label>{i18n.t('results.comment')}</Form.Label>
92                         <Form.Control
93                                 as="textarea"
94                                 isInvalid={!!(touched.comment && errors.comment)}
95                                 name="comment"
96                                 onBlur={handleBlur}
97                                 onChange={handleChange}
98                                 rows="6"
99                                 value={values.comment || ''}
100                         />
101                 </Form.Group>
102         </Modal.Body>
103         <Modal.Footer>
104                 {onCancel ?
105                         <Button onClick={onCancel} variant="secondary">
106                                 {i18n.t('button.cancel')}
107                         </Button>
108                 : null}
109                 <Button type="submit" variant="primary">
110                         {i18n.t('button.save')}
111                 </Button>
112         </Modal.Footer>
113 </Form>;
114
115 ReportForm.propTypes = {
116         errors: PropTypes.shape({
117                 comment: PropTypes.string,
118                 forfeit: PropTypes.string,
119                 time: PropTypes.string,
120                 vod: PropTypes.string,
121         }),
122         handleBlur: PropTypes.func,
123         handleChange: PropTypes.func,
124         handleSubmit: PropTypes.func,
125         onCancel: PropTypes.func,
126         round: PropTypes.shape({
127                 locked: PropTypes.bool,
128         }),
129         touched: PropTypes.shape({
130                 comment: PropTypes.bool,
131                 forfeit: PropTypes.bool,
132                 time: PropTypes.bool,
133                 vod: PropTypes.bool,
134         }),
135         values: PropTypes.shape({
136                 comment: PropTypes.string,
137                 forfeit: PropTypes.bool,
138                 time: PropTypes.string,
139                 vod: PropTypes.string,
140         }),
141 };
142
143 export default withFormik({
144         displayName: 'ReportForm',
145         enableReinitialize: true,
146         handleSubmit: async (values, actions) => {
147                 const { comment, forfeit, round_id, time, user_id, vod } = values;
148                 const { setErrors } = actions;
149                 const { onCancel } = actions.props;
150                 try {
151                         await axios.post('/api/results', {
152                                 comment,
153                                 forfeit,
154                                 round_id,
155                                 time: parseTime(time) || 0,
156                                 user_id,
157                                 vod,
158                         });
159                         toastr.success(i18n.t('results.reportSuccess'));
160                         if (onCancel) {
161                                 onCancel();
162                         }
163                 } catch (e) {
164                         toastr.error(i18n.t('results.reportError'));
165                         if (e.response && e.response.data && e.response.data.errors) {
166                                 setErrors(laravelErrorsToFormik(e.response.data.errors));
167                         }
168                 }
169         },
170         mapPropsToValues: ({ round, user }) => {
171                 const result = findResult(user, round);
172                 return {
173                         comment: result && result.comment ? result.comment : '',
174                         forfeit: result ? !!result.forfeit : false,
175                         round_id: round.id,
176                         time: result && result.time ? formatTime(result) : '',
177                         user_id: user.id,
178                         vod: result && result.vod ? result.vod : '',
179                 };
180         },
181         validationSchema: yup.object().shape({
182                 comment: yup.string(),
183                 forfeit: yup.boolean().required(),
184                 time: yup.string().time().when('forfeit', {
185                         is: false,
186                         then: () => yup.string().required().time(),
187                 }),
188                 vod: yup.string().url(),
189         }),
190 })(withTranslation()(ReportForm));