Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

Rev Autor Línea Nro. Línea
6830 stevensc 1
import React, { useEffect, useRef, useState } from 'react'
2
import { axios } from '../../../utils'
3
import { feedTypes } from '../../../redux/feed/feed.types'
4
import { deleteFeed } from '../../../redux/feed/feed.actions'
5
import { openShareModal } from '../../../redux/share-modal/shareModal.actions'
6
import { shareModalTypes } from '../../../redux/share-modal/shareModal.types'
7
import { addNotification } from '../../../redux/notification/notification.actions'
8
import { connect, useDispatch, useSelector } from 'react-redux'
9
import parse from 'html-react-parser'
10
import TungstenIcon from '@mui/icons-material/Tungsten'
11
import FavoriteIcon from '@mui/icons-material/FavoriteTwoTone'
12
import RecommendIcon from '@mui/icons-material/Recommend'
13
import AccessTimeIcon from '@mui/icons-material/AccessTime'
14
import SendOutlinedIcon from '@mui/icons-material/SendOutlined'
15
import ChatOutlinedIcon from '@mui/icons-material/ChatOutlined'
16
import ShareOutlinedIcon from '@mui/icons-material/ShareOutlined'
17
import EmojiEmotionsIcon from '@mui/icons-material/EmojiEmotions'
18
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism'
19
 
20
import InputOption from './InputOption'
21
import Avatar from '../../UI/AvatarImage'
22
import ConfirmModal from '../../modals/ConfirmModal'
23
import FeedCommentSection from '../CommentSection'
24
import withExternalShare from './withExternalShare'
25
import FeedModal from '../FeedModal'
26
import SurveyForm from '../../survey-form/SurveyForm'
27
 
6835 stevensc 28
import './Feed.scss'
7142 stevensc 29
import ReactionsButton from '../../UI/buttons/ReactionsButton'
6835 stevensc 30
 
6830 stevensc 31
const Feed = (props) => {
32
  const {
33
    isShare = false,
34
    feed_unique,
35
    feed_share_url,
36
    feed_share_external_url,
37
    feed_delete_url,
38
    feed_my_reaction,
39
    feed_reactions,
40
    owner_url,
7136 stevensc 41
    image,
6830 stevensc 42
    owner_image,
43
    owner_name,
44
    owner_description,
45
    owner_shared,
46
    owner_comments,
47
    owner_time_elapse,
48
    owner_file_image_preview,
49
    owner_file_video,
50
    owner_file_image,
51
    owner_file_document,
52
    comment_add_url,
53
    comments,
54
    shared_name,
55
    shared_image,
56
    shared_time_elapse,
57
    shared_description,
58
    shared_file_video,
59
    shared_file_image_preview,
60
    shared_file_image,
61
    owner_external_shared,
62
    shared_file_document,
63
    shared_url,
64
    feed_increment_external_counter_url,
65
    feed_content_type,
66
    feed_vote_url,
7144 stevensc 67
    feed_save_reaction_url,
68
    feed_delete_reaction_url,
6830 stevensc 69
    openShareModal, // REDUX ACTION
70
  } = props
71
  const [ownerReactions, setOwnerReaction] = useState(feed_reactions)
72
  const [totalReactions, setTotalReactions] = useState(0)
73
  const [totalComments, setTotalComments] = useState(owner_comments)
74
  const [externalShare, setExternalShare] = useState(owner_external_shared)
75
  const [sharedState, setSharedState] = useState(owner_shared)
76
  const [showComments, setShowComments] = useState(false)
77
  const [showModal, setShowModal] = useState(false)
6832 stevensc 78
  const labels = useSelector(({ intl }) => intl.labels)
6830 stevensc 79
 
80
  const reactionsOptions = [
81
    {
82
      type: 'r',
83
      icon: <RecommendIcon style={{ color: '#7405f9' }} />,
84
    },
85
    {
86
      type: 's',
87
      icon: <VolunteerActivismIcon style={{ color: '#6495ED' }} />,
88
    },
89
    {
90
      type: 'l',
91
      icon: <FavoriteIcon style={{ color: '#DF704D' }} />,
92
    },
93
    {
94
      type: 'i',
95
      icon: (
96
        <TungstenIcon
97
          style={{ color: '#F5BB5C', transform: 'rotate(180deg)' }}
98
        />
99
      ),
100
    },
101
    {
102
      type: 'f',
103
      icon: <EmojiEmotionsIcon style={{ color: '#FF7F50' }} />,
104
    },
105
  ]
106
 
107
  const handleShare = () =>
108
    openShareModal(
109
      feed_share_url,
110
      shareModalTypes.SHARE,
111
      feedTypes.DASHBOARD,
112
      feed_unique
113
    )
114
  const handleExternalShare = (value) => setExternalShare(value)
115
 
116
  const displayCommentSection = () => setShowComments(!showComments)
117
 
118
  const ExternalShareButton = withExternalShare(
119
    InputOption,
120
    feed_share_external_url,
121
    {
122
      Icon: SendOutlinedIcon,
123
      color: 'gray',
124
      title: 'Send',
125
      shareUrl: feed_increment_external_counter_url,
126
      setValue: handleExternalShare,
127
      withTitle: true,
128
    }
129
  )
130
 
131
  useEffect(() => setSharedState(owner_shared), [owner_shared])
132
 
133
  useEffect(() => {
134
    const feedReactions = ownerReactions?.reduce(
135
      (acc, reaction) => acc + Number(reaction.total),
136
 
137
    )
138
    setTotalReactions(feedReactions)
139
  }, [ownerReactions])
140
 
141
  return (
142
    <>
143
      {showModal && (
144
        <FeedModal
145
          isShow={true}
146
          feed={props}
147
          handleClose={() => setShowModal(false)}
148
        />
149
      )}
150
      <div className="feed">
151
        <Feed.Header
152
          image={owner_image}
153
          name={owner_name}
154
          timeElapsed={owner_time_elapse}
155
          viewUrl={owner_url}
156
          deleteUrl={feed_delete_url}
157
          feedUnique={feed_unique}
158
        />
159
 
160
        <div
161
          className="feed__body"
162
          onClick={() =>
163
            (owner_file_image || owner_file_video || owner_file_document) &&
164
            setShowModal(true)
165
          }
166
        >
167
          <Feed.Content
168
            description={owner_description}
169
            image={owner_file_image}
170
            imagePreview={owner_file_image_preview}
171
            video={owner_file_video}
172
            document={owner_file_document}
173
            sharedItem={{
174
              name: shared_name,
175
              image: shared_image,
176
              time_elapse: shared_time_elapse,
177
              description: shared_description,
178
              file_video: shared_file_video,
179
              file_image_preview: shared_file_image_preview,
180
              file_image: shared_file_image,
181
              file_document: shared_file_document,
182
              shared_url,
183
            }}
184
            type={feed_content_type}
185
            voteUrl={feed_vote_url}
186
          />
187
        </div>
188
 
189
        {!isShare && feed_content_type !== 'fast-survey' && (
190
          <div className="px-3 d-flex align-items-center justify-content-between">
191
            <div className="reactions-counter">
192
              {reactionsOptions
193
                .filter((option) =>
194
                  ownerReactions.find(
195
                    (reaction) => reaction.reaction === option.type
196
                  )
197
                )
198
                .map((reaction) => reaction.icon)}
199
              <span>{totalReactions} reacciones</span>
200
            </div>
201
            <div
202
              className="d-inline-flex align-items-center"
203
              style={{ gap: '5px' }}
204
            >
205
              {!!totalComments && (
6832 stevensc 206
                <span>{`${totalComments} ${labels.comments?.toLowerCase()}`}</span>
6830 stevensc 207
              )}
208
              {!!sharedState && (
6832 stevensc 209
                <span>{`${sharedState} ${labels.shared?.toLowerCase()}`}</span>
6830 stevensc 210
              )}
211
              {!!externalShare && (
6832 stevensc 212
                <span>{`${externalShare} ${labels.sends?.toLowerCase()}`}</span>
6830 stevensc 213
              )}
214
            </div>
215
          </div>
216
        )}
217
 
218
        {!isShare && feed_content_type !== 'fast-survey' && (
219
          <div className="feed__buttons">
7142 stevensc 220
            <ReactionsButton
7143 stevensc 221
              className="feed__share-option position-relative"
7142 stevensc 222
              currentReaction={feed_my_reaction}
7144 stevensc 223
              saveUrl={feed_save_reaction_url}
224
              deleteUrl={feed_delete_reaction_url}
7142 stevensc 225
              onChange={(reactions) => setOwnerReaction(reactions)}
226
              withLabel
227
            />
6830 stevensc 228
            <InputOption
229
              Icon={ChatOutlinedIcon}
6832 stevensc 230
              title={labels.comment}
6830 stevensc 231
              color="gray"
232
              onClick={displayCommentSection}
233
              withTitle
234
            />
235
            <InputOption
236
              Icon={ShareOutlinedIcon}
6832 stevensc 237
              title={labels.share}
6830 stevensc 238
              color="gray"
239
              onClick={handleShare}
240
              withTitle
241
            />
242
            <ExternalShareButton />
243
          </div>
244
        )}
245
 
246
        <div className="px-2 pb-2">
247
          <FeedCommentSection
248
            feedId={feed_unique}
7136 stevensc 249
            image={image}
6830 stevensc 250
            addUrl={comment_add_url}
251
            updateTotalComments={(total) => setTotalComments(total)}
252
            currentComments={comments}
253
            isShow={showComments}
254
          />
255
        </div>
256
      </div>
257
    </>
258
  )
259
}
260
 
261
const Content = ({
262
  description,
263
  image,
264
  imagePreview,
265
  video,
266
  document,
267
  sharedItem,
268
  type,
269
  voteUrl,
270
}) => {
271
  const [isReadMoreActive, setIsReadMoreActive] = useState(false)
6832 stevensc 272
  const labels = useSelector(({ intl }) => intl.labels)
6830 stevensc 273
 
274
  const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
275
 
6831 stevensc 276
  const htmlParsedText = (fullStringText = '') => {
6830 stevensc 277
    const fullText = parse(fullStringText)
278
    if (fullStringText.length > 500) {
279
      const shortenedString = fullStringText.substr(0, 500)
280
      const shortenedText = parse(`${shortenedString}... `)
281
      return (
282
        <>
283
          {isReadMoreActive ? fullText : shortenedText}
284
          <span className="cursor-pointer" onClick={readMoreHandler}>
6832 stevensc 285
            {isReadMoreActive ? labels.read_less : labels.read_more}
6830 stevensc 286
          </span>
287
        </>
288
      )
289
    }
290
    return <p>{fullText}</p>
291
  }
292
 
293
  return (
294
    <>
295
      {type !== 'fast-survey' ? (
296
        htmlParsedText(description)
297
      ) : (
298
        <SurveyForm
299
          active={description.active}
300
          question={description.question}
301
          answers={[
302
            description.answer1,
303
            description.answer2,
304
            description.answer3,
305
            description.answer4,
306
            description.answer5,
307
          ]}
308
          votes={
309
            description.votes1 && [
310
              description.votes1,
311
              description.votes2,
312
              description.votes3,
313
              description.votes4,
314
              description.votes5,
315
            ]
316
          }
317
          time={description.time_remaining}
318
          voteUrl={voteUrl}
319
          resultType={description.result_type}
320
        />
321
      )}
322
      {image && <img src={image} className="Entradas" loading="lazy" />}
323
      {video && (
324
        <video src={video} controls poster={imagePreview} preload="none" />
325
      )}
326
      {document && (
7140 stevensc 327
        <a href={document} download>
328
          <img className="pdf" src="/images/extension/pdf.png" alt="pdf" />
6830 stevensc 329
        </a>
330
      )}
331
      {sharedItem.name && (
332
        <div className="py-3 px-md-3">
333
          <Feed
334
            isShare={true}
335
            owner_name={sharedItem.name}
336
            owner_image={sharedItem.image}
337
            owner_time_elapse={sharedItem.time_elapse}
338
            owner_description={sharedItem.description}
339
            owner_file_video={sharedItem.file_video}
340
            owner_file_image_preview={sharedItem.file_image_preview}
341
            owner_file_image={sharedItem.file_image}
342
            owner_file_document={sharedItem.file_document}
343
            owner_url={sharedItem.shared_url}
344
          />
345
        </div>
346
      )}
347
    </>
348
  )
349
}
350
 
351
const Header = ({
352
  image = '',
353
  name = '',
354
  timeElapsed = '',
355
  deleteUrl = '',
356
  viewUrl = '',
357
  feedUnique = '',
358
}) => {
359
  const [showConfirmModal, setShowConfirmModal] = useState(false)
360
  const [displayOption, setDisplayOption] = useState(false)
361
  const deleteButton = useRef()
6832 stevensc 362
  const labels = useSelector(({ intl }) => intl.labels)
6830 stevensc 363
  const dispatch = useDispatch()
364
 
365
  const handleShowConfirmModal = () => setShowConfirmModal(!showConfirmModal)
366
 
367
  const deleteFeedHandler = () => {
368
    axios.post(deleteUrl).then((res) => {
369
      const { data } = res
370
      if (!data.success) {
371
        dispatch(addNotification({ style: 'danger', msg: data.data }))
372
        return
373
      }
374
      dispatch(addNotification({ style: 'success', msg: data.data }))
375
      handleShowConfirmModal()
376
      dispatch(deleteFeed(feedUnique))
377
    })
378
  }
379
 
380
  useEffect(() => {
381
    const handleClickOutside = (event) => {
382
      if (
383
        deleteButton.current &&
384
        !deleteButton.current.contains(event.target)
385
      ) {
386
        setDisplayOption(false)
387
      }
388
    }
389
    document.addEventListener('mousedown', handleClickOutside)
390
 
391
    return () => {
392
      document.removeEventListener('mousedown', handleClickOutside)
393
    }
394
  }, [deleteButton])
395
 
396
  return (
397
    <div className="feed__header">
398
      <div className="d-inline-flex" style={{ gap: '.5rem' }}>
399
        <Avatar imageUrl={image} name={name} size="xl" />
400
 
401
        <div className="feed__info">
402
          <a href={viewUrl}>
403
            <h2>{name}</h2>
404
          </a>
405
          <div className="time__elapse">
406
            <p>{timeElapsed}</p>
407
            <AccessTimeIcon className="time__elapse-icon" />
408
          </div>
409
        </div>
410
      </div>
411
 
412
      {deleteUrl && (
413
        <div className="cursor-pointer d-flex align-items-center position-relative">
414
          <img
415
            src="/images/icons/options.png"
416
            className="cursor-pointer img-icon options"
417
            onClick={() => setDisplayOption(!displayOption)}
418
          />
419
          <div className={`feed-options ${displayOption ? 'active' : ''}`}>
420
            <ul>
421
              <li>
422
                <button
423
                  className="option-btn"
424
                  onClick={handleShowConfirmModal}
425
                  ref={deleteButton}
426
                >
427
                  <i className="fa fa-trash-o mr-1" />
6832 stevensc 428
                  {labels.delete}
6830 stevensc 429
                </button>
430
              </li>
431
            </ul>
432
          </div>
433
          <ConfirmModal
434
            show={showConfirmModal}
435
            onClose={() => handleShowConfirmModal(false)}
436
            onAccept={deleteFeedHandler}
6832 stevensc 437
            acceptLabel={labels.accept}
6830 stevensc 438
          />
439
        </div>
440
      )}
441
    </div>
442
  )
443
}
444
 
445
Feed.Content = Content
446
Feed.Header = Header
447
 
448
const mapDispatchToProps = {
449
  addNotification: (notification) => addNotification(notification),
450
  openShareModal: (postUrl, modalType, feedType) =>
451
    openShareModal(postUrl, modalType, feedType),
452
}
453
 
454
export default connect(null, mapDispatchToProps)(Feed)