16750 |
stevensc |
1 |
import React, { useState, useEffect } from 'react'
|
|
|
2 |
import axios from 'axios'
|
|
|
3 |
import { useForm } from 'react-hook-form'
|
|
|
4 |
import { connect } from 'react-redux'
|
|
|
5 |
import { Button, Modal } from 'react-bootstrap'
|
|
|
6 |
import Datetime from 'react-datetime'
|
|
|
7 |
import 'react-datetime/css/react-datetime.css'
|
|
|
8 |
|
|
|
9 |
import { addNotification } from '../../../redux/notification/notification.actions'
|
|
|
10 |
import { closeSurveyModal } from '../../../redux/survey-modal/surveyModal.actions'
|
|
|
11 |
import { addFeed, fetchFeeds } from '../../../redux/feed/feed.actions'
|
|
|
12 |
|
|
|
13 |
const SurveyModal = (props) => {
|
|
|
14 |
const { addNotification, addFeed } = props // Redux actions
|
|
|
15 |
const { postUrl, isOpen, currentPage, timelineUrl } = props // Redux states
|
|
|
16 |
const [loading, setLoading] = useState(false)
|
|
|
17 |
const [selectedDate, setSelectedDate] = useState(null)
|
|
|
18 |
const [optionsNumber, setOptionsNumber] = useState(2)
|
|
|
19 |
|
|
|
20 |
const { register, handleSubmit, setValue, clearErrors, reset } = useForm()
|
|
|
21 |
|
|
|
22 |
const options = [
|
|
|
23 |
{ placeholder: 'Por ejemplo: transporte público' },
|
|
|
24 |
{ placeholder: 'Por ejemplo: coche propio' },
|
|
|
25 |
{ placeholder: 'Por ejemplo: coche compartido' },
|
|
|
26 |
{ placeholder: 'Por ejemplo: bicicleta' },
|
|
|
27 |
{ placeholder: 'Por ejemplo: otro' }
|
|
|
28 |
]
|
|
|
29 |
|
|
|
30 |
const calculateMaxDate = () => {
|
|
|
31 |
const today = new Date()
|
|
|
32 |
const maxDate = today.setDate(today.getDate() + 29)
|
|
|
33 |
return new Date(maxDate)
|
|
|
34 |
}
|
|
|
35 |
|
|
|
36 |
const calculateMinDate = () => {
|
|
|
37 |
return new Date()
|
|
|
38 |
}
|
|
|
39 |
|
|
|
40 |
const handleChange = (selected) => {
|
|
|
41 |
setSelectedDate(selected)
|
|
|
42 |
|
|
|
43 |
if (!selected) {
|
|
|
44 |
return null
|
|
|
45 |
}
|
|
|
46 |
|
|
|
47 |
const currentDate = new Date()
|
|
|
48 |
const selectedDt = new Date(selected.format('YYYY-MM-DD HH:mm'))
|
|
|
49 |
const timeDiff = selectedDt.getTime() - currentDate.getTime()
|
|
|
50 |
const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24))
|
|
|
51 |
const hoursDiff = Math.floor((timeDiff / (1000 * 60 * 60)) % 24)
|
|
|
52 |
const minutesDiff = Math.floor((timeDiff / (1000 * 60)) % 60)
|
|
|
53 |
|
|
|
54 |
setValue('duration_days', daysDiff)
|
|
|
55 |
setValue('duration_hours', hoursDiff)
|
|
|
56 |
setValue('duration_minutes', minutesDiff)
|
|
|
57 |
}
|
|
|
58 |
|
|
|
59 |
const addOption = () => {
|
|
|
60 |
setOptionsNumber(optionsNumber + 1)
|
|
|
61 |
}
|
|
|
62 |
|
|
|
63 |
const removeOption = () => {
|
|
|
64 |
setOptionsNumber(optionsNumber - 1)
|
|
|
65 |
}
|
|
|
66 |
|
|
|
67 |
const onSubmit = handleSubmit((data) => {
|
|
|
68 |
setLoading(true)
|
|
|
69 |
const formData = new FormData()
|
|
|
70 |
|
|
|
71 |
Object.entries(data).map(([entry, value]) => formData.append(entry, value))
|
|
|
72 |
|
|
|
73 |
for (let i = 1; i <= 5; i++) {
|
|
|
74 |
!data[`answer${i}`] && formData.append(`answer${i}`, '')
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
const numberOfAnswers = Object.entries(data).filter((entry) =>
|
|
|
78 |
entry[0].includes('answer')
|
|
|
79 |
).length
|
|
|
80 |
|
|
|
81 |
formData.append('feed_content_type', 'fast-survey')
|
|
|
82 |
formData.append('number_of_answers', numberOfAnswers)
|
|
|
83 |
formData.append('posted_or_shared', 'POST')
|
|
|
84 |
|
|
|
85 |
axios
|
|
|
86 |
.post(postUrl, formData)
|
|
|
87 |
.then(({ data: response }) => {
|
|
|
88 |
const { success, data } = response
|
|
|
89 |
if (!success) {
|
|
|
90 |
typeof data !== 'string'
|
|
|
91 |
? Object.entries(data).map(([key, value]) =>
|
|
|
92 |
addNotification({ style: 'danger', msg: `${key}: ${value[0]}` })
|
|
|
93 |
)
|
|
|
94 |
: addNotification({ style: 'danger', msg: data })
|
|
|
95 |
return
|
|
|
96 |
}
|
|
|
97 |
|
|
|
98 |
if (currentPage && timelineUrl) {
|
|
|
99 |
fetchFeeds(timelineUrl, currentPage)
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
addFeed(data)
|
|
|
103 |
|
|
|
104 |
addNotification({
|
|
|
105 |
style: 'success',
|
|
|
106 |
msg: 'La publicación ha sido compartida'
|
|
|
107 |
})
|
|
|
108 |
reset()
|
|
|
109 |
clearErrors()
|
|
|
110 |
closeSurveyModal()
|
|
|
111 |
})
|
|
|
112 |
.catch((err) => {
|
|
|
113 |
addNotification({ style: 'danger', msg: `Error: ${err}` })
|
|
|
114 |
throw new Error(err)
|
|
|
115 |
})
|
|
|
116 |
.finally(() => setLoading(false))
|
|
|
117 |
})
|
|
|
118 |
|
|
|
119 |
useEffect(() => {
|
|
|
120 |
clearErrors()
|
|
|
121 |
}, [isOpen])
|
|
|
122 |
|
|
|
123 |
useEffect(() => {
|
|
|
124 |
register('duration_days')
|
|
|
125 |
register('duration_hours')
|
|
|
126 |
register('duration_minutes')
|
|
|
127 |
}, [])
|
|
|
128 |
|
|
|
129 |
return (
|
|
|
130 |
<Modal show={isOpen} onHide={closeSurveyModal}>
|
|
|
131 |
<form onSubmit={onSubmit} method="post">
|
|
|
132 |
<Modal.Header closeButton>
|
|
|
133 |
<Modal.Title>Encuestas rápidas</Modal.Title>
|
|
|
134 |
</Modal.Header>
|
|
|
135 |
<Modal.Body>
|
|
|
136 |
<div className="form-row">
|
|
|
137 |
<div className="form-group col">
|
|
|
138 |
<label htmlFor="privacy">Privacidad</label>
|
|
|
139 |
<select
|
|
|
140 |
className="form-control"
|
|
|
141 |
name="privacy"
|
|
|
142 |
id="privacy"
|
|
|
143 |
ref={register}
|
|
|
144 |
>
|
|
|
145 |
<option value="c">Compañía</option>
|
|
|
146 |
<option value="p">Público</option>
|
|
|
147 |
</select>
|
|
|
148 |
</div>
|
|
|
149 |
<div className="form-group col">
|
|
|
150 |
<label htmlFor="result_type">Resultado</label>
|
|
|
151 |
<select
|
|
|
152 |
className="form-control"
|
|
|
153 |
name="result_type"
|
|
|
154 |
id="result_type"
|
|
|
155 |
ref={register}
|
|
|
156 |
>
|
|
|
157 |
<option value="pr">Privado</option>
|
|
|
158 |
<option value="pu">Público</option>
|
|
|
159 |
</select>
|
|
|
160 |
</div>
|
|
|
161 |
</div>
|
|
|
162 |
<div className="form-group">
|
|
|
163 |
<label htmlFor="question">Tu pregunta*</label>
|
|
|
164 |
<input
|
|
|
165 |
type="text"
|
|
|
166 |
className="form-control"
|
|
|
167 |
placeholder="Por ejemplo: ¿cómo te desplazas al trabajo?"
|
|
|
168 |
maxLength={1024}
|
|
|
169 |
id="question"
|
|
|
170 |
name="question"
|
|
|
171 |
ref={register({ required: true })}
|
|
|
172 |
/>
|
|
|
173 |
</div>
|
|
|
174 |
{options.slice(0, optionsNumber).map((option, index) => (
|
|
|
175 |
<div className="form-group" key={index}>
|
|
|
176 |
<label htmlFor={`answer${index + 1}`}>Opción {index + 1}*</label>
|
|
|
177 |
{index > 1 && (
|
|
|
178 |
<button className="btn" onClick={removeOption}>
|
|
|
179 |
Eliminar
|
|
|
180 |
</button>
|
|
|
181 |
)}
|
|
|
182 |
<input
|
|
|
183 |
type="text"
|
|
|
184 |
className="form-control"
|
|
|
185 |
placeholder={option.placeholder}
|
|
|
186 |
maxLength={100}
|
|
|
187 |
id={`answer${index + 1}`}
|
|
|
188 |
name={`answer${index + 1}`}
|
|
|
189 |
ref={register({ required: true })}
|
|
|
190 |
/>
|
|
|
191 |
</div>
|
|
|
192 |
))}
|
|
|
193 |
{optionsNumber < options.length && (
|
|
|
194 |
<button
|
|
|
195 |
className="btn btn-outline-primary rounded"
|
|
|
196 |
onClick={addOption}
|
|
|
197 |
>
|
|
|
198 |
Añadir opción
|
|
|
199 |
</button>
|
|
|
200 |
)}
|
|
|
201 |
<div className="form-group">
|
|
|
202 |
<label htmlFor="question">Duración</label>
|
|
|
203 |
<Datetime
|
|
|
204 |
dateFormat="DD/MM/YYYY"
|
|
|
205 |
onChange={handleChange}
|
|
|
206 |
isValidDate={(current) =>
|
|
|
207 |
current.isBefore(calculateMaxDate()) &&
|
|
|
208 |
current.isAfter(calculateMinDate())
|
|
|
209 |
} // Se valida que la fecha esté entre la fecha mínima y la fecha máxima
|
|
|
210 |
value={selectedDate}
|
|
|
211 |
/>
|
|
|
212 |
</div>
|
|
|
213 |
</Modal.Body>
|
|
|
214 |
<Modal.Footer>
|
|
|
215 |
<Button size="sm" type="submit" disabled={loading}>
|
|
|
216 |
Enviar
|
|
|
217 |
</Button>
|
|
|
218 |
<Button
|
|
|
219 |
variant="light"
|
|
|
220 |
size="sm"
|
|
|
221 |
disabled={loading}
|
|
|
222 |
onClick={closeSurveyModal}
|
|
|
223 |
>
|
|
|
224 |
Cancelar
|
|
|
225 |
</Button>
|
|
|
226 |
</Modal.Footer>
|
|
|
227 |
</form>
|
|
|
228 |
</Modal>
|
|
|
229 |
)
|
|
|
230 |
}
|
|
|
231 |
|
|
|
232 |
const mapStateToProps = (state) => ({
|
|
|
233 |
isOpen: state.surveyModal.isOpen,
|
|
|
234 |
postUrl: state.surveyModal.postUrl,
|
|
|
235 |
currentPage: state.feed.currentPage,
|
|
|
236 |
timelineUrl: state.feed.timelineUrl
|
|
|
237 |
})
|
|
|
238 |
|
|
|
239 |
const mapDispatchToProps = {
|
|
|
240 |
addNotification: (notification) => addNotification(notification),
|
|
|
241 |
closeSurveyModal: () => closeSurveyModal(),
|
|
|
242 |
addFeed: (feed) => addFeed(feed)
|
|
|
243 |
}
|
|
|
244 |
|
|
|
245 |
export default connect(mapStateToProps, mapDispatchToProps)(SurveyModal)
|