Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 16755 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
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
 
16752 stevensc 9
import { addFeed, fetchFeeds } from '../../../redux/feed/feed.actions'
16750 stevensc 10
import { addNotification } from '../../../redux/notification/notification.actions'
11
import { closeSurveyModal } from '../../../redux/survey-modal/surveyModal.actions'
12
 
13
const SurveyModal = (props) => {
16755 stevensc 14
  const { addNotification, addFeed, closeSurveyModal } = props // Redux actions
16753 stevensc 15
  const { postUrl, isOpen, currentPage, timelineUrl, state } = props // Redux states
16750 stevensc 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
 
16752 stevensc 67
  const closeModal = () => {
68
    closeSurveyModal()
69
  }
70
 
16750 stevensc 71
  const onSubmit = handleSubmit((data) => {
72
    setLoading(true)
73
    const formData = new FormData()
74
 
75
    Object.entries(data).map(([entry, value]) => formData.append(entry, value))
76
 
77
    for (let i = 1; i <= 5; i++) {
78
      !data[`answer${i}`] && formData.append(`answer${i}`, '')
79
    }
80
 
81
    const numberOfAnswers = Object.entries(data).filter((entry) =>
82
      entry[0].includes('answer')
83
    ).length
84
 
85
    formData.append('feed_content_type', 'fast-survey')
86
    formData.append('number_of_answers', numberOfAnswers)
87
    formData.append('posted_or_shared', 'POST')
88
 
89
    axios
90
      .post(postUrl, formData)
91
      .then(({ data: response }) => {
92
        const { success, data } = response
93
        if (!success) {
94
          typeof data !== 'string'
95
            ? Object.entries(data).map(([key, value]) =>
96
                addNotification({ style: 'danger', msg: `${key}: ${value[0]}` })
97
              )
98
            : addNotification({ style: 'danger', msg: data })
99
          return
100
        }
101
 
102
        if (currentPage && timelineUrl) {
103
          fetchFeeds(timelineUrl, currentPage)
104
        }
105
 
106
        addFeed(data)
107
 
108
        addNotification({
109
          style: 'success',
110
          msg: 'La publicación ha sido compartida'
111
        })
112
        reset()
113
        clearErrors()
16752 stevensc 114
        closeModal()
16750 stevensc 115
      })
116
      .catch((err) => {
117
        addNotification({ style: 'danger', msg: `Error: ${err}` })
118
        throw new Error(err)
119
      })
120
      .finally(() => setLoading(false))
121
  })
122
 
123
  useEffect(() => {
124
    clearErrors()
125
  }, [isOpen])
126
 
127
  useEffect(() => {
128
    register('duration_days')
129
    register('duration_hours')
130
    register('duration_minutes')
131
  }, [])
132
 
133
  return (
16752 stevensc 134
    <Modal show={isOpen} onHide={closeModal}>
16750 stevensc 135
      <form onSubmit={onSubmit} method="post">
136
        <Modal.Header closeButton>
16757 stevensc 137
          <Modal.Title>Encuesta rápida</Modal.Title>
16750 stevensc 138
        </Modal.Header>
139
        <Modal.Body>
140
          <div className="form-row">
141
            <div className="form-group col">
142
              <label htmlFor="privacy">Privacidad</label>
143
              <select
144
                className="form-control"
145
                name="privacy"
146
                id="privacy"
147
                ref={register}
148
              >
149
                <option value="c">Compañía</option>
150
                <option value="p">Público</option>
151
              </select>
152
            </div>
153
            <div className="form-group col">
154
              <label htmlFor="result_type">Resultado</label>
155
              <select
156
                className="form-control"
157
                name="result_type"
158
                id="result_type"
159
                ref={register}
160
              >
161
                <option value="pr">Privado</option>
162
                <option value="pu">Público</option>
163
              </select>
164
            </div>
165
          </div>
166
          <div className="form-group">
167
            <label htmlFor="question">Tu pregunta*</label>
168
            <input
169
              type="text"
170
              className="form-control"
171
              placeholder="Por ejemplo: ¿cómo te desplazas al trabajo?"
172
              maxLength={1024}
173
              id="question"
174
              name="question"
175
              ref={register({ required: true })}
176
            />
177
          </div>
178
          {options.slice(0, optionsNumber).map((option, index) => (
179
            <div className="form-group" key={index}>
180
              <label htmlFor={`answer${index + 1}`}>Opción {index + 1}*</label>
181
              {index > 1 && (
182
                <button className="btn" onClick={removeOption}>
183
                  Eliminar
184
                </button>
185
              )}
186
              <input
187
                type="text"
188
                className="form-control"
189
                placeholder={option.placeholder}
190
                maxLength={100}
191
                id={`answer${index + 1}`}
192
                name={`answer${index + 1}`}
193
                ref={register({ required: true })}
194
              />
195
            </div>
196
          ))}
197
          {optionsNumber < options.length && (
198
            <button
199
              className="btn btn-outline-primary rounded"
200
              onClick={addOption}
201
            >
202
              Añadir opción
203
            </button>
204
          )}
205
          <div className="form-group">
206
            <label htmlFor="question">Duración</label>
207
            <Datetime
208
              dateFormat="DD/MM/YYYY"
209
              onChange={handleChange}
210
              isValidDate={(current) =>
211
                current.isBefore(calculateMaxDate()) &&
212
                current.isAfter(calculateMinDate())
213
              } // Se valida que la fecha esté entre la fecha mínima y la fecha máxima
214
              value={selectedDate}
215
            />
216
          </div>
217
        </Modal.Body>
218
        <Modal.Footer>
219
          <Button size="sm" type="submit" disabled={loading}>
220
            Enviar
221
          </Button>
222
          <Button
223
            variant="light"
224
            size="sm"
225
            disabled={loading}
16755 stevensc 226
            onClick={closeModal}
16750 stevensc 227
          >
228
            Cancelar
229
          </Button>
230
        </Modal.Footer>
231
      </form>
232
    </Modal>
233
  )
234
}
235
 
236
const mapStateToProps = (state) => ({
237
  isOpen: state.surveyModal.isOpen,
238
  postUrl: state.surveyModal.postUrl,
239
  currentPage: state.feed.currentPage,
16753 stevensc 240
  timelineUrl: state.feed.timelineUrl,
241
  state: state
16750 stevensc 242
})
243
 
244
const mapDispatchToProps = {
245
  addNotification: (notification) => addNotification(notification),
246
  closeSurveyModal: () => closeSurveyModal(),
247
  addFeed: (feed) => addFeed(feed)
248
}
249
 
250
export default connect(mapStateToProps, mapDispatchToProps)(SurveyModal)