Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

Rev Autor Línea Nro. Línea
6618 stevensc 1
import React, { useEffect, useState, useRef } from 'react'
2
import { useDispatch, useSelector } from 'react-redux'
3
import { axios } from '../../../utils'
4
import {
5
  EmailIcon,
6
  EmailShareButton,
7
  FacebookIcon,
8
  FacebookShareButton,
9
  RedditIcon,
10
  RedditShareButton,
11
  TelegramIcon,
12
  TelegramShareButton,
13
  TwitterIcon,
14
  TwitterShareButton,
15
  WhatsappIcon,
16
  WhatsappShareButton,
17
} from 'react-share'
18
import parse from 'html-react-parser'
19
import RecommendIcon from '@mui/icons-material/Recommend'
20
import FavoriteIcon from '@mui/icons-material/FavoriteTwoTone'
21
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism'
22
import EmojiEmotionsIcon from '@mui/icons-material/EmojiEmotions'
23
import TungstenIcon from '@mui/icons-material/Tungsten'
24
import GroupsRoundedIcon from '@mui/icons-material/GroupsRounded'
25
 
26
import { feedTypes } from '../../redux/feed/feed.types'
27
import { shareModalTypes } from '../../../redux/share-modal/shareModal.types'
28
 
29
import { deleteFeed } from '../../redux/feed/feed.actions'
30
import { openShareModal } from '../../../redux/share-modal/shareModal.actions'
31
import { addNotification } from '../../../redux/notification/notification.actions'
32
 
33
import FeedCommentSection from './CommentSection'
34
import useOutsideClick from '../../hooks/useOutsideClick'
35
 
36
import FeedModal from './FeedModal'
37
import ConfirmModal from '../modals/ConfirmModal'
6623 stevensc 38
import SurveyForm from '../survey-form/SurveyForm'
6625 stevensc 39
import ReactionsButton from '../UI/buttons/ReactionsButton'
6618 stevensc 40
 
41
const Feed = ({ feed, owner_shared, image }) => {
42
  const {
43
    feed_unique,
44
    owner_name,
45
    owner_url,
46
    owner_image,
47
    owner_time_elapse,
48
    owner_file_image,
49
    owner_file_video,
50
    owner_file_document,
51
    owner_feed_type,
52
    feed_highlighted,
53
    feed_share_url,
54
    feed_delete_url,
55
    comments,
56
    comment_add_url,
57
    feed_share_external_url,
58
  } = feed
6624 stevensc 59
  const [totalComments, setTotalComments] = useState(0)
6618 stevensc 60
  const [ownerReactions, setOwnerReaction] = useState(feed.feed_reactions)
61
  const [totalReactions, setTotalReactions] = useState(0)
62
  const [sharedState, setSharedState] = useState(owner_shared)
63
  const [shareUrl, setShareUrl] = useState('')
64
 
65
  const [showComments, setShowComments] = useState(false)
66
  const [shareOptions, setShareOptions] = useState(false)
67
  const [show, setShow] = useState(false)
68
 
69
  const shareContainer = useRef(null)
70
  const dispatch = useDispatch()
6625 stevensc 71
 
6618 stevensc 72
  useOutsideClick(shareContainer, () => setShareOptions(false))
73
 
74
  const reactionsOptions = [
75
    {
76
      type: 'r',
77
      icon: <RecommendIcon style={{ color: '#7405f9' }} />,
78
    },
79
    {
80
      type: 's',
81
      icon: <VolunteerActivismIcon style={{ color: '#6495ED' }} />,
82
    },
83
    {
84
      type: 'l',
85
      icon: <FavoriteIcon style={{ color: '#DF704D' }} />,
86
    },
87
    {
88
      type: 'i',
89
      icon: (
90
        <TungstenIcon
91
          style={{ color: '#F5BB5C', transform: 'rotate(180deg)' }}
92
        />
93
      ),
94
    },
95
    {
96
      type: 'f',
97
      icon: <EmojiEmotionsIcon style={{ color: '#FF7F50' }} />,
98
    },
99
  ]
100
 
101
  const getShareUrl = new Promise((resolve, reject) => {
102
    if (shareOptions) {
103
      axios
104
        .get(feed_share_external_url)
105
        .then(({ data }) => {
106
          if (!data.success) {
107
            dispatch(addNotification({ style: 'danger', msg: data.data }))
108
            setShareOptions(false)
109
            return reject(data.data)
110
          }
111
          setShareUrl(data.data)
112
          return resolve(data.data)
113
        })
114
        .catch((err) => reject(err))
115
    }
116
  })
117
 
6625 stevensc 118
  const displayComments = () => {
119
    setShowComments(!showComments)
6618 stevensc 120
  }
121
 
122
  const btnShareHandler = () => {
123
    dispatch(
124
      openShareModal(
125
        feed_share_url,
126
        shareModalTypes.SHARE,
127
        feedTypes.DASHBOARD,
128
        feed_unique
129
      )
130
    )
131
  }
132
 
133
  useEffect(() => setSharedState(owner_shared), [owner_shared])
134
 
135
  useEffect(() => {
6842 stevensc 136
    const feedReactions = ownerReactions?.reduce(
6618 stevensc 137
      (acc, reaction) => acc + Number(reaction.total),
138
 
139
    )
140
    setTotalReactions(feedReactions)
141
  }, [ownerReactions])
142
 
143
  return (
144
    <>
145
      <FeedModal isShow={show} handleClose={() => setShow(false)} feed={feed} />
146
      <div className={`feed ${feed_highlighted ? 'highlighted' : ''}`}>
147
        <FeedHeader
148
          ownerName={owner_name}
149
          ownerImage={owner_image}
150
          ownerTimeElapse={owner_time_elapse}
151
          ownerUrl={owner_url}
152
          feedDeleteUrl={feed_delete_url}
153
          feedUnique={feed_unique}
154
          feedType={owner_feed_type}
155
        />
156
        <div
157
          onClick={() =>
158
            (owner_file_image || owner_file_video || owner_file_document) &&
159
            setShow(true)
160
          }
161
        >
162
          <Feed.Content
163
            isShare={!!feed.shared_name}
6623 stevensc 164
            image={feed.owner_file_image}
165
            fileVideo={feed.owner_file_video}
166
            imagePreview={feed.owner_file_image_preview}
167
            document={feed.owner_file_document}
168
            description={feed.owner_description}
169
            type={feed.feed_content_type}
170
            voteUrl={feed.feed_vote_url}
6618 stevensc 171
            sharedItem={{
172
              name: feed.shared_name,
173
              image: feed.shared_image,
174
              time_elapse: feed.shared_time_elapse,
175
              description: feed.shared_description,
176
              file_video: feed.shared_file_video,
177
              file_image_preview: feed.shared_file_image_preview,
178
              file_image: feed.shared_file_image,
179
              file_document: feed.shared_file_document,
180
            }}
181
          />
182
        </div>
183
        <div className="reactions-counter">
184
          {reactionsOptions
185
            .filter((option) =>
186
              ownerReactions.find(
187
                (reaction) => reaction.reaction === option.type
188
              )
189
            )
190
            .map((reaction) => reaction.icon)}
191
          <span>{totalReactions} reacciones</span>
192
        </div>
193
        <ul className="reactions-list">
194
          <li>
6625 stevensc 195
            <ReactionsButton
196
              onChange={(reactions) => setOwnerReaction(reactions)}
197
              currentReaction={feed.feed_my_reaction}
198
              withLabel
199
              deleteUrl={feed.feed_delete_reaction_url}
200
              reactionTypesUrl={{
201
                r: feed.feed_save_reaction_recommended_url,
202
                s: feed.feed_save_reaction_support_url,
203
                l: feed.feed_save_reaction_love_url,
204
                i: feed.feed_save_reaction_interest_url,
205
                f: feed.feed_save_reaction_fun_url,
206
              }}
207
            />
6618 stevensc 208
          </li>
209
          <li>
210
            <button
211
              type="button"
212
              id={`btn-comments-${feed_unique}`}
213
              className="btn-indicator"
214
              onClick={displayComments}
215
            >
216
              <img src="/images/icons/message.png" className="mr-1 img-icon" />
217
              {totalComments}
218
            </button>
219
          </li>
220
          <li>
221
            <button
222
              type="button"
223
              id={`btn-share-${feed_unique}`}
224
              className="btn-indicator"
225
              onClick={btnShareHandler}
226
            >
227
              <img src="/images/icons/share.png" className="mr-1 img-icon" />
228
              {sharedState}
229
            </button>
230
          </li>
231
          <li className="position-relative">
232
            <button
233
              type="button"
234
              className="btn-indicator"
235
              onClick={() => setShareOptions(!shareOptions)}
236
            >
237
              <i className="mr-1 far fa-share-square" />
238
            </button>
239
            {shareOptions && (
240
              <div className="ext_share" ref={shareContainer}>
241
                <FacebookShareButton
242
                  beforeOnClick={() => getShareUrl}
243
                  url={shareUrl}
244
                >
245
                  <FacebookIcon size={32} round />
246
                </FacebookShareButton>
247
                <TwitterShareButton
248
                  beforeOnClick={() => getShareUrl}
249
                  url={shareUrl}
250
                >
251
                  <TwitterIcon size={32} round />
252
                </TwitterShareButton>
253
                <TelegramShareButton
254
                  beforeOnClick={() => getShareUrl}
255
                  url={shareUrl}
256
                >
257
                  <TelegramIcon size={32} round />
258
                </TelegramShareButton>
259
                <WhatsappShareButton
260
                  beforeOnClick={() => getShareUrl}
261
                  url={shareUrl}
262
                >
263
                  <WhatsappIcon size={32} round />
264
                </WhatsappShareButton>
265
                <RedditShareButton
266
                  beforeOnClick={() => getShareUrl}
267
                  url={shareUrl}
268
                >
269
                  <RedditIcon size={32} round />
270
                </RedditShareButton>
271
                <EmailShareButton
272
                  beforeOnClick={() => getShareUrl}
273
                  url={shareUrl}
274
                >
275
                  <EmailIcon size={32} round />
276
                </EmailShareButton>
277
              </div>
278
            )}
279
          </li>
280
        </ul>
281
        <FeedCommentSection
6625 stevensc 282
          isShow={showComments}
6618 stevensc 283
          image={image}
284
          addUrl={comment_add_url}
285
          currentComments={comments}
6625 stevensc 286
          updateTotalComments={(totalComments) =>
287
            setTotalComments(totalComments)
288
          }
6618 stevensc 289
        />
290
      </div>
291
    </>
292
  )
293
}
294
 
295
export const FeedContent = ({
296
  showDescription = true,
6623 stevensc 297
  image,
298
  video,
299
  imagePreview,
300
  document,
301
  description,
6618 stevensc 302
  isShare,
303
  sharedItem,
6623 stevensc 304
  type,
305
  voteUrl,
6618 stevensc 306
}) => {
307
  return (
308
    <div className="job_descp">
6623 stevensc 309
      {type !== 'fast-survey' && showDescription ? (
310
        <Feed.Description description={description} />
311
      ) : (
312
        <SurveyForm
313
          active={description.active}
314
          question={description.question}
315
          answers={[
316
            description.answer1,
317
            description.answer2,
318
            description.answer3,
319
            description.answer4,
320
            description.answer5,
321
          ]}
322
          votes={
323
            description.votes1 && [
324
              description.votes1,
325
              description.votes2,
326
              description.votes3,
327
              description.votes4,
328
              description.votes5,
329
            ]
330
          }
331
          time={description.time_remaining}
332
          voteUrl={voteUrl}
333
          resultType={description.result_type}
334
        />
6618 stevensc 335
      )}
6623 stevensc 336
 
337
      {image && <img src={image} className="Entradas" loading="lazy" />}
338
      {video && (
339
        <video src={video} controls poster={imagePreview} preload="none" />
6618 stevensc 340
      )}
6623 stevensc 341
      {document && (
7089 stevensc 342
        <a href={document} download target="_blank" rel="noreferrer">
343
          <img className="pdf" src="/images/extension/pdf.png" alt="pdf" />
6618 stevensc 344
        </a>
345
      )}
346
      {isShare && (
347
        <Feed.Shared
348
          name={sharedItem.name}
349
          image={sharedItem.image}
350
          timeElapse={sharedItem.time_elapse}
351
          description={sharedItem.description}
6623 stevensc 352
          video={sharedItem.file_video}
353
          imagePreview={sharedItem.file_image_preview}
354
          document={sharedItem.file_document}
6618 stevensc 355
        />
356
      )}
357
    </div>
358
  )
359
}
6623 stevensc 360
export const FeedDescription = ({ description }) => {
6618 stevensc 361
  const [isReadMoreActive, setIsReadMoreActive] = useState(false)
6832 stevensc 362
  const labels = useSelector(({ intl }) => intl.labels)
6618 stevensc 363
 
364
  const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
365
 
366
  const htmlParsedText = (fullStringText) => {
367
    const fullText = parse(fullStringText)
368
    if (fullStringText.length > 500) {
369
      const shortenedString = fullStringText.substr(0, 500)
370
      const shortenedText = parse(`${shortenedString}... `)
371
      return (
372
        <p>
373
          {isReadMoreActive ? fullText : shortenedText}
374
          <span className="cursor-pointer" onClick={readMoreHandler}>
6832 stevensc 375
            {isReadMoreActive ? labels.read_less : labels.read_more}
6618 stevensc 376
          </span>
377
        </p>
378
      )
379
    }
380
    return <p>{fullText}</p>
381
  }
382
 
6623 stevensc 383
  return <div className="show-read-more">{htmlParsedText(description)}</div>
6618 stevensc 384
}
385
 
386
export const FeedShared = ({
387
  name,
388
  image,
389
  timeElapse,
390
  description,
6623 stevensc 391
  video,
392
  imagePreview,
393
  document,
6618 stevensc 394
}) => {
395
  const [isReadMoreActive, setIsReadMoreActive] = useState(false)
6832 stevensc 396
  const labels = useSelector(({ intl }) => intl.labels)
6618 stevensc 397
 
398
  const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
399
 
6831 stevensc 400
  const htmlParsedText = (fullStringText = '') => {
6618 stevensc 401
    const fullText = parse(fullStringText)
402
    if (fullStringText.length > 500) {
403
      const shortenedString = fullStringText.substr(0, 500)
404
      const shortenedText = parse(`${shortenedString}... `)
405
      return (
406
        <p>
407
          {isReadMoreActive ? fullText : shortenedText}
408
          <span className="cursor-pointer" onClick={readMoreHandler}>
6832 stevensc 409
            {isReadMoreActive ? labels.read_less : labels.read_more}
6618 stevensc 410
          </span>
411
        </p>
412
      )
413
    }
414
    return <p>{fullText}</p>
415
  }
416
 
417
  return (
418
    <div className="shared-post-bar">
419
      <div className="post-bar">
420
        <div className="post_topbar">
421
          <div className="usy-dt">
422
            <img src={image} alt="" style={{ width: '50px', height: 'auto' }} />
423
            <div className="usy-name">
424
              <h3>{name}</h3>
425
              <span>{timeElapse}</span>
426
            </div>
427
          </div>
428
        </div>
429
        <div className="job_descp">
430
          <div className="show-read-more">{htmlParsedText(description)}</div>
6623 stevensc 431
          {image && <img src={image} className="Entradas" loading="lazy" />}
432
          {video && (
433
            <video src={video} controls poster={imagePreview} preload="none" />
6618 stevensc 434
          )}
6623 stevensc 435
          {document && (
436
            <a href={document} target="_blank" rel="noreferrer">
6832 stevensc 437
              {labels.download}
6618 stevensc 438
            </a>
439
          )}
440
        </div>
441
      </div>
442
    </div>
443
  )
444
}
445
 
446
export const FeedHeader = ({
447
  ownerName,
448
  ownerImage,
449
  ownerTimeElapse,
450
  ownerUrl,
451
  feedDeleteUrl,
452
  feedUnique,
453
  feedType,
454
}) => {
455
  const [showConfirmModal, setShowConfirmModal] = useState(false)
456
  const [displayOption, setDisplayOption] = useState(false)
457
  const deleteButton = useRef(null)
458
  const labels = useSelector(({ intl }) => intl.labels)
459
  const dispatch = useDispatch()
460
  useOutsideClick(deleteButton, () => setDisplayOption(false))
461
 
462
  const handleShowConfirmModal = () => {
463
    setShowConfirmModal(!showConfirmModal)
464
  }
465
 
466
  const deleteFeedHandler = () => {
467
    axios.post(feedDeleteUrl).then((res) => {
468
      const { data } = res
469
      if (!data.success) {
470
        dispatch(addNotification({ style: 'danger', msg: data.data }))
471
        return
472
      }
473
      dispatch(addNotification({ style: 'success', msg: data.data }))
474
      handleShowConfirmModal()
475
      dispatch(deleteFeed(feedUnique))
476
    })
477
  }
478
 
479
  return (
480
    <>
481
      <div className="post_topbar">
482
        <div className="usy-dt">
483
          <a href={ownerUrl}>
484
            <img
485
              src={ownerImage}
486
              alt=""
487
              style={{ width: '50px', height: 'auto' }}
488
            />
489
          </a>
490
          <div className="usy-name">
491
            <a href={ownerUrl}>
492
              <h3>{ownerName}</h3>
493
            </a>
494
            <span>
495
              {feedType === 'g' && <GroupsRoundedIcon />}
496
              {ownerTimeElapse}
497
            </span>
498
          </div>
499
        </div>
500
        {feedDeleteUrl && (
501
          <div className="cursor-pointer d-flex align-items-center">
502
            <img
503
              src="/images/icons/options.png"
504
              className="cursor-pointer img-icon options"
505
              onClick={() => setDisplayOption(!displayOption)}
506
            />
507
            <div className={`feed-options ${displayOption ? 'active' : ''}`}>
508
              <ul>
509
                <li>
510
                  <button
511
                    className="option-btn"
512
                    onClick={handleShowConfirmModal}
513
                    ref={deleteButton}
514
                  >
515
                    <i className="fa fa-trash-o mr-1" />
516
                    {labels.delete}
517
                  </button>
518
                </li>
519
              </ul>
520
            </div>
521
            <ConfirmModal
522
              show={showConfirmModal}
523
              onClose={() => handleShowConfirmModal(false)}
524
              onAccept={deleteFeedHandler}
525
              acceptLabel="Aceptar"
526
            />
527
          </div>
528
        )}
529
      </div>
530
    </>
531
  )
532
}
533
 
534
Feed.Shared = FeedShared
535
Feed.Description = FeedDescription
536
Feed.Content = FeedContent
537
Feed.Header = FeedHeader
538
 
539
export default React.memo(Feed)