Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 16732 | Rev 16734 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
11166 stevensc 1
import React, { useState, useEffect } from 'react'
2
import axios from 'axios'
16685 stevensc 3
import { config } from './helpers/ckeditor_config'
4
import { useForm } from 'react-hook-form'
16686 stevensc 5
import { connect } from 'react-redux'
16682 stevensc 6
import { Button, Modal } from 'react-bootstrap'
16685 stevensc 7
import { CKEditor } from 'ckeditor4-react'
16696 stevensc 8
import Datetime from 'react-datetime'
16697 stevensc 9
import 'react-datetime/css/react-datetime.css'
16685 stevensc 10
 
16671 stevensc 11
import {
12
  closeShareModal,
13
  setModalType
14
} from '../redux/share-modal/shareModal.actions'
11166 stevensc 15
import { addFeed, fetchFeeds } from '../redux/feed/feed.actions'
16
import { addNotification } from '../redux/notification/notification.actions'
16685 stevensc 17
 
18
import { shareModalTypes } from '../redux/share-modal/shareModal.types'
19
 
11166 stevensc 20
import Spinner from './Spinner'
16685 stevensc 21
import DropzoneComponent from './Dropzone/DropzoneComponent'
7386 stevensc 22
 
16685 stevensc 23
const ShareModal = (props) => {
24
  const { addNotification, closeShareModal, setModalType, addFeed } = props // Redux actions
25
  const { postUrl, isOpen, modalType, currentPage, timelineUrl, feedSharedId } =
26
    props // Redux states
27
  const [loading, setLoading] = useState(false)
28
 
16671 stevensc 29
  const {
30
    register,
31
    errors,
32
    handleSubmit,
33
    setValue,
34
    getValues,
35
    clearErrors,
16699 stevensc 36
    unregister,
16671 stevensc 37
    reset
16681 stevensc 38
  } = useForm()
7388 stevensc 39
 
16671 stevensc 40
  const recomendationText = {
41
    IMAGE: 'Tamaño recomendado: 720x720',
42
    FILE: 'solo documentos PDF',
43
    VIDEO: 'Video de extensión mp4, mpeg, webm'
44
  }
15353 stevensc 45
 
16681 stevensc 46
  const closeModal = () => {
16685 stevensc 47
    closeShareModal()
16681 stevensc 48
  }
7386 stevensc 49
 
16681 stevensc 50
  const onUploadedHandler = (files) => {
51
    setValue('file', files)
52
    clearErrors('file')
53
  }
7386 stevensc 54
 
16683 stevensc 55
  const onSubmit = handleSubmit((data) => {
16712 stevensc 56
    //setLoading(true)
16683 stevensc 57
    const formData = new FormData()
7390 stevensc 58
 
16683 stevensc 59
    Object.entries(data).map(([entry, value]) => formData.append(entry, value))
7386 stevensc 60
 
16732 stevensc 61
    for (let i = 1; i <= 5; i++) {
16733 stevensc 62
      data[`answer${i}`]
63
        ? formData.append(`answer${i}`, data[`answer${i}`])
64
        : formData.append(`answer${i}`)
16731 stevensc 65
    }
66
 
16710 stevensc 67
    if (modalType === shareModalTypes.SURVEY) {
68
      const numberOfAnswers = Object.entries(data).filter((entry) =>
69
        entry[0].includes('answer')
70
      ).length
71
 
72
      formData.append('feed_content_type', 'fast-survey')
16723 stevensc 73
      formData.append('number_of_answers', numberOfAnswers)
16710 stevensc 74
    }
16712 stevensc 75
 
16722 stevensc 76
    axios
16685 stevensc 77
      .post(postUrl, formData)
78
      .then(({ data: response }) => {
79
        const { success, data } = response
80
        if (!success) {
81
          typeof data !== 'string'
82
            ? Object.entries(data).map(([key, value]) =>
83
                addNotification({ style: 'danger', msg: `${key}: ${value[0]}` })
16671 stevensc 84
              )
16685 stevensc 85
            : addNotification({ style: 'danger', msg: data })
16671 stevensc 86
          return
87
        }
7386 stevensc 88
 
16685 stevensc 89
        if (currentPage && timelineUrl) {
90
          fetchFeeds(timelineUrl, currentPage)
91
        }
15215 stevensc 92
 
16685 stevensc 93
        if (feedSharedId) {
94
          addFeed(data, feedSharedId)
95
          return
96
        }
7806 stevensc 97
 
16685 stevensc 98
        addFeed(data)
99
        addNotification({
100
          style: 'success',
101
          msg: 'La publicación ha sido compartida'
102
        })
103
        reset()
104
        clearErrors()
16671 stevensc 105
        closeModal()
106
      })
16685 stevensc 107
      .catch((err) => {
108
        addNotification({ style: 'danger', msg: `Error: ${err}` })
109
        throw new Error(err)
110
      })
16722 stevensc 111
      .finally(() => setLoading(false))
16683 stevensc 112
  })
7806 stevensc 113
 
16681 stevensc 114
  useEffect(() => {
115
    clearErrors()
116
  }, [isOpen])
7806 stevensc 117
 
16681 stevensc 118
  useEffect(() => {
119
    register('posted_or_shared')
120
    setValue('posted_or_shared', shareModalTypes.POST)
121
 
122
    if (
123
      [
124
        shareModalTypes.IMAGE,
125
        shareModalTypes.VIDEO,
126
        shareModalTypes.FILE,
127
        shareModalTypes.SHARE,
128
        shareModalTypes.CHAT
16684 stevensc 129
      ].includes(modalType)
16681 stevensc 130
    ) {
131
      register('file', { required: 'El campo es requerido' })
132
    }
133
 
134
    if (modalType === shareModalTypes.POST) {
135
      register('description', { required: 'El campo es requerido' })
136
    }
16696 stevensc 137
 
138
    if (modalType === shareModalTypes.SURVEY) {
16699 stevensc 139
      unregister('description')
16717 stevensc 140
      register('duration_days')
141
      register('duration_hours')
142
      register('duration_minutes')
16696 stevensc 143
    }
16681 stevensc 144
  }, [modalType])
145
 
16671 stevensc 146
  return (
16681 stevensc 147
    <Modal show={isOpen} onHide={closeModal}>
16687 stevensc 148
      <form onSubmit={onSubmit} method="post">
149
        <Modal.Header closeButton>
150
          <Modal.Title>Compartir una publicación</Modal.Title>
151
        </Modal.Header>
152
        <Modal.Body>
16675 stevensc 153
          {!loading ? (
16671 stevensc 154
            <>
16676 stevensc 155
              {modalType === shareModalTypes.SURVEY && (
16696 stevensc 156
                <SurveyForm register={register} setValue={setValue} />
16676 stevensc 157
              )}
16675 stevensc 158
              {modalType !== shareModalTypes.SURVEY && (
159
                <>
160
                  <CKEditor
161
                    onChange={(e) =>
162
                      setValue('description', e.editor.getData())
163
                    }
164
                    config={config}
165
                  />
166
                  {errors.description && <p>{errors.description.message}</p>}
167
                </>
168
              )}
16671 stevensc 169
              {![shareModalTypes.POST, shareModalTypes.SURVEY].includes(
170
                modalType
171
              ) && (
16677 stevensc 172
                <>
173
                  <DropzoneComponent
174
                    modalType={modalType}
175
                    onUploaded={onUploadedHandler}
176
                    settedFile={getValues('file')}
177
                    recomendationText={recomendationText[modalType]}
178
                  />
179
                  {errors.file && <p>{errors.file.message}</p>}
180
                </>
16671 stevensc 181
              )}
182
            </>
16675 stevensc 183
          ) : (
184
            <Spinner />
16671 stevensc 185
          )}
16687 stevensc 186
        </Modal.Body>
187
        <Modal.Footer>
188
          <Button size="sm" type="submit" disabled={loading}>
189
            Enviar
190
          </Button>
191
          <Button
16690 stevensc 192
            variant="light"
16687 stevensc 193
            size="sm"
194
            disabled={loading}
195
            onClick={closeShareModal}
196
          >
197
            Cancelar
198
          </Button>
199
          <Button
16690 stevensc 200
            variant="outline-info"
16687 stevensc 201
            size="sm"
202
            disabled={loading}
203
            onClick={() => setModalType(shareModalTypes.SURVEY)}
204
          >
205
            Añadir encuesta
206
          </Button>
207
        </Modal.Footer>
208
      </form>
16671 stevensc 209
    </Modal>
210
  )
211
}
7386 stevensc 212
 
16696 stevensc 213
const SurveyForm = ({ register, setValue }) => {
16714 stevensc 214
  const [selectedDate, setSelectedDate] = useState(null)
16717 stevensc 215
  const [daysDifference, setDaysDifference] = useState({
216
    days: null,
217
    hours: null,
218
    minutes: null
219
  })
16671 stevensc 220
  const [optionsNumber, setOptionsNumber] = useState(2)
7386 stevensc 221
 
16671 stevensc 222
  const options = [
223
    { placeholder: 'Por ejemplo: transporte público' },
224
    { placeholder: 'Por ejemplo: coche propio' },
225
    { placeholder: 'Por ejemplo: coche compartido' },
226
    { placeholder: 'Por ejemplo: bicicleta' },
227
    { placeholder: 'Por ejemplo: otro' }
228
  ]
229
 
16704 stevensc 230
  const calculateMaxDate = () => {
231
    const today = new Date()
16705 stevensc 232
    const maxDate = today.setDate(today.getDate() + 29)
16704 stevensc 233
    return new Date(maxDate)
234
  }
235
 
16705 stevensc 236
  const calculateMinDate = () => {
237
    return new Date()
238
  }
239
 
16713 stevensc 240
  const handleChange = (selected) => {
16714 stevensc 241
    setSelectedDate(selected)
242
 
243
    if (selected) {
16716 stevensc 244
      const currentDate = new Date()
16721 stevensc 245
      const selectedDt = new Date(selected.format('YYYY-MM-DD HH:mm'))
16716 stevensc 246
      const timeDiff = selectedDt.getTime() - currentDate.getTime()
16720 stevensc 247
      const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24))
248
      const hoursDiff = Math.floor((timeDiff / (1000 * 60 * 60)) % 24)
249
      const minutesDiff = Math.floor((timeDiff / (1000 * 60)) % 60)
250
 
16717 stevensc 251
      setDaysDifference({
252
        days: daysDiff,
253
        hours: hoursDiff,
254
        minutes: minutesDiff
255
      })
16714 stevensc 256
    } else {
257
      setDaysDifference(null)
258
    }
16713 stevensc 259
  }
260
 
16671 stevensc 261
  const addOption = () => {
16674 stevensc 262
    setOptionsNumber(optionsNumber + 1)
16671 stevensc 263
  }
264
 
265
  const removeOption = () => {
16674 stevensc 266
    setOptionsNumber(optionsNumber - 1)
16671 stevensc 267
  }
268
 
16714 stevensc 269
  useEffect(() => {
16717 stevensc 270
    setValue('duration_days', daysDifference.days)
271
    setValue('duration_hours', daysDifference.hours)
272
    setValue('duration_minutes', daysDifference.minutes)
16714 stevensc 273
  }, [daysDifference])
274
 
16671 stevensc 275
  return (
276
    <>
16709 stevensc 277
      <div className="form-row">
278
        <div className="form-group col">
279
          <label htmlFor="privacy">Privacidad</label>
280
          <select
281
            className="form-control"
282
            name="privacy"
283
            id="privacy"
284
            ref={register}
285
          >
286
            <option value="c">Compañía</option>
287
            <option value="p">Público</option>
288
          </select>
289
        </div>
290
        <div className="form-group col">
16710 stevensc 291
          <label htmlFor="result_type">Resultado</label>
16709 stevensc 292
          <select
293
            className="form-control"
16710 stevensc 294
            name="result_type"
295
            id="result_type"
16709 stevensc 296
            ref={register}
297
          >
298
            <option value="pr">Privado</option>
299
            <option value="pu">Público</option>
300
          </select>
301
        </div>
16694 stevensc 302
      </div>
303
      <div className="form-group">
16671 stevensc 304
        <label htmlFor="question">Tu pregunta*</label>
305
        <input
306
          type="text"
307
          className="form-control"
308
          placeholder="Por ejemplo: ¿cómo te desplazas al trabajo?"
309
          maxLength={140}
310
          id="question"
311
          name="question"
312
          ref={register({ required: true })}
313
        />
314
      </div>
315
      {options.slice(0, optionsNumber).map((option, index) => (
316
        <div className="form-group" key={index}>
16710 stevensc 317
          <label htmlFor={`answer${index + 1}`}>Opción {index + 1}*</label>
16671 stevensc 318
          {index > 1 && (
319
            <button className="btn" onClick={removeOption}>
320
              Eliminar
321
            </button>
322
          )}
323
          <input
324
            type="text"
325
            className="form-control"
326
            placeholder={option.placeholder}
327
            maxLength={30}
16710 stevensc 328
            id={`answer${index + 1}`}
329
            name={`answer${index + 1}`}
16671 stevensc 330
            ref={register({ required: true })}
331
          />
332
        </div>
333
      ))}
16675 stevensc 334
      {optionsNumber < options.length && (
335
        <button className="btn btn-outline-primary rounded" onClick={addOption}>
336
          Añadir opción
337
        </button>
338
      )}
16710 stevensc 339
      <div className="form-group">
340
        <label htmlFor="question">Duración</label>
341
        <Datetime
342
          dateFormat="DD/MM/YYYY"
16713 stevensc 343
          onChange={handleChange}
16710 stevensc 344
          isValidDate={(current) =>
345
            current.isBefore(calculateMaxDate()) &&
346
            current.isAfter(calculateMinDate())
347
          } // Se valida que la fecha esté entre la fecha mínima y la fecha máxima
16715 stevensc 348
          value={selectedDate}
16710 stevensc 349
        />
350
      </div>
16671 stevensc 351
    </>
352
  )
11166 stevensc 353
}
7386 stevensc 354
 
16685 stevensc 355
const mapStateToProps = (state) => ({
356
  isOpen: state.shareModal.isOpen,
357
  postUrl: state.shareModal.postUrl,
358
  modalType: state.shareModal.modalType,
359
  feedSharedId: state.shareModal.feedSharedId,
360
  currentPage: state.feed.currentPage,
361
  timelineUrl: state.feed.timelineUrl
362
})
363
 
364
const mapDispatchToProps = {
365
  addNotification: (notification) => addNotification(notification),
366
  closeShareModal: () => closeShareModal(),
367
  setModalType: (modalType) => setModalType(modalType),
368
  addFeed: (feed, feedSharedId) => addFeed(feed, feedSharedId)
369
}
370
 
371
export default connect(mapStateToProps, mapDispatchToProps)(ShareModal)