Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 16710 | Rev 16712 | 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) => {
16671 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
 
16710 stevensc 61
    if (modalType === shareModalTypes.SURVEY) {
62
      const numberOfAnswers = Object.entries(data).filter((entry) =>
63
        entry[0].includes('answer')
64
      ).length
65
 
66
      formData.append('feed_content_type', 'fast-survey')
67
      formData.append('`number_of_answers', numberOfAnswers)
68
    }
16696 stevensc 69
    /* axios
16685 stevensc 70
      .post(postUrl, formData)
71
      .then(({ data: response }) => {
72
        const { success, data } = response
73
        if (!success) {
74
          typeof data !== 'string'
75
            ? Object.entries(data).map(([key, value]) =>
76
                addNotification({ style: 'danger', msg: `${key}: ${value[0]}` })
16671 stevensc 77
              )
16685 stevensc 78
            : addNotification({ style: 'danger', msg: data })
16671 stevensc 79
          return
80
        }
7386 stevensc 81
 
16685 stevensc 82
        if (currentPage && timelineUrl) {
83
          fetchFeeds(timelineUrl, currentPage)
84
        }
15215 stevensc 85
 
16685 stevensc 86
        if (feedSharedId) {
87
          addFeed(data, feedSharedId)
88
          return
89
        }
7806 stevensc 90
 
16685 stevensc 91
        addFeed(data)
92
        addNotification({
93
          style: 'success',
94
          msg: 'La publicación ha sido compartida'
95
        })
96
        reset()
97
        clearErrors()
16671 stevensc 98
        closeModal()
99
      })
16685 stevensc 100
      .catch((err) => {
101
        addNotification({ style: 'danger', msg: `Error: ${err}` })
102
        throw new Error(err)
103
      })
16696 stevensc 104
      .finally(() => setLoading(false)) */
16683 stevensc 105
  })
7806 stevensc 106
 
16681 stevensc 107
  useEffect(() => {
108
    clearErrors()
109
  }, [isOpen])
7806 stevensc 110
 
16681 stevensc 111
  useEffect(() => {
112
    register('posted_or_shared')
113
    setValue('posted_or_shared', shareModalTypes.POST)
114
 
115
    if (
116
      [
117
        shareModalTypes.IMAGE,
118
        shareModalTypes.VIDEO,
119
        shareModalTypes.FILE,
120
        shareModalTypes.SHARE,
121
        shareModalTypes.CHAT
16684 stevensc 122
      ].includes(modalType)
16681 stevensc 123
    ) {
124
      register('file', { required: 'El campo es requerido' })
125
    }
126
 
127
    if (modalType === shareModalTypes.POST) {
128
      register('description', { required: 'El campo es requerido' })
129
    }
16696 stevensc 130
 
131
    if (modalType === shareModalTypes.SURVEY) {
16699 stevensc 132
      unregister('description')
16697 stevensc 133
      register('date')
16696 stevensc 134
    }
16681 stevensc 135
  }, [modalType])
136
 
16671 stevensc 137
  return (
16681 stevensc 138
    <Modal show={isOpen} onHide={closeModal}>
16687 stevensc 139
      <form onSubmit={onSubmit} method="post">
140
        <Modal.Header closeButton>
141
          <Modal.Title>Compartir una publicación</Modal.Title>
142
        </Modal.Header>
143
        <Modal.Body>
16675 stevensc 144
          {!loading ? (
16671 stevensc 145
            <>
16676 stevensc 146
              {modalType === shareModalTypes.SURVEY && (
16696 stevensc 147
                <SurveyForm register={register} setValue={setValue} />
16676 stevensc 148
              )}
16675 stevensc 149
              {modalType !== shareModalTypes.SURVEY && (
150
                <>
151
                  <CKEditor
152
                    onChange={(e) =>
153
                      setValue('description', e.editor.getData())
154
                    }
155
                    config={config}
156
                  />
157
                  {errors.description && <p>{errors.description.message}</p>}
158
                </>
159
              )}
16671 stevensc 160
              {![shareModalTypes.POST, shareModalTypes.SURVEY].includes(
161
                modalType
162
              ) && (
16677 stevensc 163
                <>
164
                  <DropzoneComponent
165
                    modalType={modalType}
166
                    onUploaded={onUploadedHandler}
167
                    settedFile={getValues('file')}
168
                    recomendationText={recomendationText[modalType]}
169
                  />
170
                  {errors.file && <p>{errors.file.message}</p>}
171
                </>
16671 stevensc 172
              )}
173
            </>
16675 stevensc 174
          ) : (
175
            <Spinner />
16671 stevensc 176
          )}
16687 stevensc 177
        </Modal.Body>
178
        <Modal.Footer>
179
          <Button size="sm" type="submit" disabled={loading}>
180
            Enviar
181
          </Button>
182
          <Button
16690 stevensc 183
            variant="light"
16687 stevensc 184
            size="sm"
185
            disabled={loading}
186
            onClick={closeShareModal}
187
          >
188
            Cancelar
189
          </Button>
190
          <Button
16690 stevensc 191
            variant="outline-info"
16687 stevensc 192
            size="sm"
193
            disabled={loading}
194
            onClick={() => setModalType(shareModalTypes.SURVEY)}
195
          >
196
            Añadir encuesta
197
          </Button>
198
        </Modal.Footer>
199
      </form>
16671 stevensc 200
    </Modal>
201
  )
202
}
7386 stevensc 203
 
16696 stevensc 204
const SurveyForm = ({ register, setValue }) => {
16671 stevensc 205
  const [optionsNumber, setOptionsNumber] = useState(2)
7386 stevensc 206
 
16671 stevensc 207
  const options = [
208
    { placeholder: 'Por ejemplo: transporte público' },
209
    { placeholder: 'Por ejemplo: coche propio' },
210
    { placeholder: 'Por ejemplo: coche compartido' },
211
    { placeholder: 'Por ejemplo: bicicleta' },
212
    { placeholder: 'Por ejemplo: otro' }
213
  ]
214
 
16704 stevensc 215
  const calculateMaxDate = () => {
216
    const today = new Date()
16705 stevensc 217
    const maxDate = today.setDate(today.getDate() + 29)
16704 stevensc 218
    return new Date(maxDate)
219
  }
220
 
16705 stevensc 221
  const calculateMinDate = () => {
222
    return new Date()
223
  }
224
 
16671 stevensc 225
  const addOption = () => {
16674 stevensc 226
    setOptionsNumber(optionsNumber + 1)
16671 stevensc 227
  }
228
 
229
  const removeOption = () => {
16674 stevensc 230
    setOptionsNumber(optionsNumber - 1)
16671 stevensc 231
  }
232
 
233
  return (
234
    <>
16709 stevensc 235
      <div className="form-row">
236
        <div className="form-group col">
237
          <label htmlFor="privacy">Privacidad</label>
238
          <select
239
            className="form-control"
240
            name="privacy"
241
            id="privacy"
242
            ref={register}
243
          >
244
            <option value="c">Compañía</option>
245
            <option value="p">Público</option>
246
          </select>
247
        </div>
248
        <div className="form-group col">
16710 stevensc 249
          <label htmlFor="result_type">Resultado</label>
16709 stevensc 250
          <select
251
            className="form-control"
16710 stevensc 252
            name="result_type"
253
            id="result_type"
16709 stevensc 254
            ref={register}
255
          >
256
            <option value="pr">Privado</option>
257
            <option value="pu">Público</option>
258
          </select>
259
        </div>
16694 stevensc 260
      </div>
261
      <div className="form-group">
16671 stevensc 262
        <label htmlFor="question">Tu pregunta*</label>
263
        <input
264
          type="text"
265
          className="form-control"
266
          placeholder="Por ejemplo: ¿cómo te desplazas al trabajo?"
267
          maxLength={140}
268
          id="question"
269
          name="question"
270
          ref={register({ required: true })}
271
        />
272
      </div>
273
      {options.slice(0, optionsNumber).map((option, index) => (
274
        <div className="form-group" key={index}>
16710 stevensc 275
          <label htmlFor={`answer${index + 1}`}>Opción {index + 1}*</label>
16671 stevensc 276
          {index > 1 && (
277
            <button className="btn" onClick={removeOption}>
278
              Eliminar
279
            </button>
280
          )}
281
          <input
282
            type="text"
283
            className="form-control"
284
            placeholder={option.placeholder}
285
            maxLength={30}
16710 stevensc 286
            id={`answer${index + 1}`}
287
            name={`answer${index + 1}`}
16671 stevensc 288
            ref={register({ required: true })}
289
          />
290
        </div>
291
      ))}
16675 stevensc 292
      {optionsNumber < options.length && (
293
        <button className="btn btn-outline-primary rounded" onClick={addOption}>
294
          Añadir opción
295
        </button>
296
      )}
16710 stevensc 297
      <div className="form-group">
298
        <label htmlFor="question">Duración</label>
299
        <Datetime
300
          dateFormat="DD/MM/YYYY"
301
          timeFormat="HH:mm"
302
          onChange={(e) => setValue('date', e.day)}
303
          isValidDate={(current) =>
304
            current.isBefore(calculateMaxDate()) &&
305
            current.isAfter(calculateMinDate())
306
          } // Se valida que la fecha esté entre la fecha mínima y la fecha máxima
307
          timeConstraints={{
308
            hours: { max: 23 },
309
            minutes: { max: 59 }
310
          }}
311
        />
312
      </div>
16671 stevensc 313
    </>
314
  )
11166 stevensc 315
}
7386 stevensc 316
 
16685 stevensc 317
const mapStateToProps = (state) => ({
318
  isOpen: state.shareModal.isOpen,
319
  postUrl: state.shareModal.postUrl,
320
  modalType: state.shareModal.modalType,
321
  feedSharedId: state.shareModal.feedSharedId,
322
  currentPage: state.feed.currentPage,
323
  timelineUrl: state.feed.timelineUrl
324
})
325
 
326
const mapDispatchToProps = {
327
  addNotification: (notification) => addNotification(notification),
328
  closeShareModal: () => closeShareModal(),
329
  setModalType: (modalType) => setModalType(modalType),
330
  addFeed: (feed, feedSharedId) => addFeed(feed, feedSharedId)
331
}
332
 
333
export default connect(mapStateToProps, mapDispatchToProps)(ShareModal)