Proyectos de Subversion LeadersLinked - Backend

Rev

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