Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 16685 | Rev 16687 | 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'
8
 
16671 stevensc 9
import {
10
  closeShareModal,
11
  setModalType
12
} from '../redux/share-modal/shareModal.actions'
11166 stevensc 13
import { addFeed, fetchFeeds } from '../redux/feed/feed.actions'
14
import { addNotification } from '../redux/notification/notification.actions'
16685 stevensc 15
 
16
import { shareModalTypes } from '../redux/share-modal/shareModal.types'
17
 
11166 stevensc 18
import Spinner from './Spinner'
16685 stevensc 19
import DropzoneComponent from './Dropzone/DropzoneComponent'
7386 stevensc 20
 
16685 stevensc 21
const ShareModal = (props) => {
22
  const { addNotification, closeShareModal, setModalType, addFeed } = props // Redux actions
23
  const { postUrl, isOpen, modalType, currentPage, timelineUrl, feedSharedId } =
24
    props // Redux states
25
  const [loading, setLoading] = useState(false)
26
 
16671 stevensc 27
  const {
28
    register,
29
    errors,
30
    handleSubmit,
31
    setValue,
32
    getValues,
33
    clearErrors,
34
    reset
16681 stevensc 35
  } = useForm()
7388 stevensc 36
 
16671 stevensc 37
  const recomendationText = {
38
    IMAGE: 'Tamaño recomendado: 720x720',
39
    FILE: 'solo documentos PDF',
40
    VIDEO: 'Video de extensión mp4, mpeg, webm'
41
  }
15353 stevensc 42
 
16681 stevensc 43
  const closeModal = () => {
16685 stevensc 44
    closeShareModal()
16681 stevensc 45
  }
7386 stevensc 46
 
16681 stevensc 47
  const onUploadedHandler = (files) => {
48
    setValue('file', files)
49
    clearErrors('file')
50
  }
7386 stevensc 51
 
16683 stevensc 52
  const onSubmit = handleSubmit((data) => {
16671 stevensc 53
    setLoading(true)
16683 stevensc 54
    const formData = new FormData()
7390 stevensc 55
 
16683 stevensc 56
    Object.entries(data).map(([entry, value]) => formData.append(entry, value))
7386 stevensc 57
 
16671 stevensc 58
    axios
16685 stevensc 59
      .post(postUrl, formData)
60
      .then(({ data: response }) => {
61
        const { success, data } = response
62
        if (!success) {
63
          typeof data !== 'string'
64
            ? Object.entries(data).map(([key, value]) =>
65
                addNotification({ style: 'danger', msg: `${key}: ${value[0]}` })
16671 stevensc 66
              )
16685 stevensc 67
            : addNotification({ style: 'danger', msg: data })
16671 stevensc 68
          return
69
        }
7386 stevensc 70
 
16685 stevensc 71
        if (currentPage && timelineUrl) {
72
          fetchFeeds(timelineUrl, currentPage)
73
        }
15215 stevensc 74
 
16685 stevensc 75
        if (feedSharedId) {
76
          addFeed(data, feedSharedId)
77
          return
78
        }
7806 stevensc 79
 
16685 stevensc 80
        addFeed(data)
81
        addNotification({
82
          style: 'success',
83
          msg: 'La publicación ha sido compartida'
84
        })
85
        reset()
86
        clearErrors()
16671 stevensc 87
        closeModal()
88
      })
16685 stevensc 89
      .catch((err) => {
90
        addNotification({ style: 'danger', msg: `Error: ${err}` })
91
        throw new Error(err)
92
      })
93
      .finally(() => setLoading(false))
16683 stevensc 94
  })
7806 stevensc 95
 
16681 stevensc 96
  useEffect(() => {
97
    clearErrors()
98
  }, [isOpen])
7806 stevensc 99
 
16681 stevensc 100
  useEffect(() => {
101
    register('posted_or_shared')
102
    setValue('posted_or_shared', shareModalTypes.POST)
103
 
104
    if (
105
      [
106
        shareModalTypes.IMAGE,
107
        shareModalTypes.VIDEO,
108
        shareModalTypes.FILE,
109
        shareModalTypes.SHARE,
110
        shareModalTypes.CHAT
16684 stevensc 111
      ].includes(modalType)
16681 stevensc 112
    ) {
113
      register('file', { required: 'El campo es requerido' })
114
    }
115
 
116
    if (modalType === shareModalTypes.POST) {
117
      register('description', { required: 'El campo es requerido' })
118
    }
119
  }, [modalType])
120
 
16671 stevensc 121
  return (
16681 stevensc 122
    <Modal show={isOpen} onHide={closeModal}>
16679 stevensc 123
      <Modal.Header closeButton>
124
        <Modal.Title>Compartir una publicación</Modal.Title>
125
      </Modal.Header>
126
      <Modal.Body>
16683 stevensc 127
        <form onSubmit={onSubmit} method="post">
16675 stevensc 128
          {!loading ? (
16671 stevensc 129
            <>
16676 stevensc 130
              {modalType === shareModalTypes.SURVEY && (
131
                <SurveyForm register={register} />
132
              )}
16675 stevensc 133
              {modalType !== shareModalTypes.SURVEY && (
134
                <>
135
                  <CKEditor
136
                    onChange={(e) =>
137
                      setValue('description', e.editor.getData())
138
                    }
139
                    config={config}
140
                  />
141
                  {errors.description && <p>{errors.description.message}</p>}
142
                </>
143
              )}
16671 stevensc 144
              {![shareModalTypes.POST, shareModalTypes.SURVEY].includes(
145
                modalType
146
              ) && (
16677 stevensc 147
                <>
148
                  <DropzoneComponent
149
                    modalType={modalType}
150
                    onUploaded={onUploadedHandler}
151
                    settedFile={getValues('file')}
152
                    recomendationText={recomendationText[modalType]}
153
                  />
154
                  {errors.file && <p>{errors.file.message}</p>}
155
                </>
16671 stevensc 156
              )}
157
            </>
16675 stevensc 158
          ) : (
159
            <Spinner />
16671 stevensc 160
          )}
16679 stevensc 161
 
16680 stevensc 162
          <div className="d-inline-flex mt-3 gap-3">
16682 stevensc 163
            <Button size="sm" type="submit" disabled={loading}>
16680 stevensc 164
              Enviar
16682 stevensc 165
            </Button>
166
            <Button
167
              size="sm"
168
              className="btn-secondary"
16680 stevensc 169
              disabled={loading}
16682 stevensc 170
              onClick={closeShareModal}
16680 stevensc 171
            >
172
              Cancelar
16682 stevensc 173
            </Button>
174
            <Button
175
              size="sm"
176
              className="btn-tertiary"
16680 stevensc 177
              disabled={loading}
16685 stevensc 178
              onClick={() => setModalType(shareModalTypes.SURVEY)}
16680 stevensc 179
            >
180
              Añadir encuesta
16682 stevensc 181
            </Button>
16680 stevensc 182
          </div>
16679 stevensc 183
        </form>
184
      </Modal.Body>
16671 stevensc 185
    </Modal>
186
  )
187
}
7386 stevensc 188
 
16675 stevensc 189
const SurveyForm = ({ register }) => {
16671 stevensc 190
  const [optionsNumber, setOptionsNumber] = useState(2)
7386 stevensc 191
 
16671 stevensc 192
  const options = [
193
    { placeholder: 'Por ejemplo: transporte público' },
194
    { placeholder: 'Por ejemplo: coche propio' },
195
    { placeholder: 'Por ejemplo: coche compartido' },
196
    { placeholder: 'Por ejemplo: bicicleta' },
197
    { placeholder: 'Por ejemplo: otro' }
198
  ]
199
 
200
  const addOption = () => {
16674 stevensc 201
    setOptionsNumber(optionsNumber + 1)
16671 stevensc 202
  }
203
 
204
  const removeOption = () => {
16674 stevensc 205
    setOptionsNumber(optionsNumber - 1)
16671 stevensc 206
  }
207
 
208
  return (
209
    <>
210
      <div className="form-group">
211
        <label htmlFor="question">Tu pregunta*</label>
212
        <input
213
          type="text"
214
          className="form-control"
215
          placeholder="Por ejemplo: ¿cómo te desplazas al trabajo?"
216
          maxLength={140}
217
          id="question"
218
          name="question"
219
          ref={register({ required: true })}
220
        />
221
      </div>
222
      {options.slice(0, optionsNumber).map((option, index) => (
223
        <div className="form-group" key={index}>
224
          <label htmlFor={`option-${index + 1}`}>Opción {index + 1}*</label>
225
          {index > 1 && (
226
            <button className="btn" onClick={removeOption}>
227
              Eliminar
228
            </button>
229
          )}
230
          <input
231
            type="text"
232
            className="form-control"
233
            placeholder={option.placeholder}
234
            maxLength={30}
235
            id={`option-${index + 1}`}
236
            name={`option-${index + 1}`}
237
            ref={register({ required: true })}
238
          />
239
        </div>
240
      ))}
16675 stevensc 241
      {optionsNumber < options.length && (
242
        <button className="btn btn-outline-primary rounded" onClick={addOption}>
243
          Añadir opción
244
        </button>
245
      )}
16671 stevensc 246
    </>
247
  )
11166 stevensc 248
}
7386 stevensc 249
 
16685 stevensc 250
const mapStateToProps = (state) => ({
251
  isOpen: state.shareModal.isOpen,
252
  postUrl: state.shareModal.postUrl,
253
  modalType: state.shareModal.modalType,
254
  feedSharedId: state.shareModal.feedSharedId,
255
  currentPage: state.feed.currentPage,
256
  timelineUrl: state.feed.timelineUrl
257
})
258
 
259
const mapDispatchToProps = {
260
  addNotification: (notification) => addNotification(notification),
261
  closeShareModal: () => closeShareModal(),
262
  setModalType: (modalType) => setModalType(modalType),
263
  addFeed: (feed, feedSharedId) => addFeed(feed, feedSharedId)
264
}
265
 
266
export default connect(mapStateToProps, mapDispatchToProps)(ShareModal)