Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 6831 | Rev 6842 | 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(() => {
136
    const feedReactions = ownerReactions.reduce(
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
}) => {
6832 stevensc 307
  const labels = useSelector(({ intl }) => intl.labels)
6618 stevensc 308
 
309
  return (
310
    <div className="job_descp">
6623 stevensc 311
      {type !== 'fast-survey' && showDescription ? (
312
        <Feed.Description description={description} />
313
      ) : (
314
        <SurveyForm
315
          active={description.active}
316
          question={description.question}
317
          answers={[
318
            description.answer1,
319
            description.answer2,
320
            description.answer3,
321
            description.answer4,
322
            description.answer5,
323
          ]}
324
          votes={
325
            description.votes1 && [
326
              description.votes1,
327
              description.votes2,
328
              description.votes3,
329
              description.votes4,
330
              description.votes5,
331
            ]
332
          }
333
          time={description.time_remaining}
334
          voteUrl={voteUrl}
335
          resultType={description.result_type}
336
        />
6618 stevensc 337
      )}
6623 stevensc 338
 
339
      {image && <img src={image} className="Entradas" loading="lazy" />}
340
      {video && (
341
        <video src={video} controls poster={imagePreview} preload="none" />
6618 stevensc 342
      )}
6623 stevensc 343
      {document && (
344
        <a href={document} target="_blank" rel="noreferrer">
6832 stevensc 345
          {labels.download}
6618 stevensc 346
        </a>
347
      )}
348
      {isShare && (
349
        <Feed.Shared
350
          name={sharedItem.name}
351
          image={sharedItem.image}
352
          timeElapse={sharedItem.time_elapse}
353
          description={sharedItem.description}
6623 stevensc 354
          video={sharedItem.file_video}
355
          imagePreview={sharedItem.file_image_preview}
356
          document={sharedItem.file_document}
6618 stevensc 357
        />
358
      )}
359
    </div>
360
  )
361
}
6623 stevensc 362
export const FeedDescription = ({ description }) => {
6618 stevensc 363
  const [isReadMoreActive, setIsReadMoreActive] = useState(false)
6832 stevensc 364
  const labels = useSelector(({ intl }) => intl.labels)
6618 stevensc 365
 
366
  const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
367
 
368
  const htmlParsedText = (fullStringText) => {
369
    const fullText = parse(fullStringText)
370
    if (fullStringText.length > 500) {
371
      const shortenedString = fullStringText.substr(0, 500)
372
      const shortenedText = parse(`${shortenedString}... `)
373
      return (
374
        <p>
375
          {isReadMoreActive ? fullText : shortenedText}
376
          <span className="cursor-pointer" onClick={readMoreHandler}>
6832 stevensc 377
            {isReadMoreActive ? labels.read_less : labels.read_more}
6618 stevensc 378
          </span>
379
        </p>
380
      )
381
    }
382
    return <p>{fullText}</p>
383
  }
384
 
6623 stevensc 385
  return <div className="show-read-more">{htmlParsedText(description)}</div>
6618 stevensc 386
}
387
 
388
export const FeedShared = ({
389
  name,
390
  image,
391
  timeElapse,
392
  description,
6623 stevensc 393
  video,
394
  imagePreview,
395
  document,
6618 stevensc 396
}) => {
397
  const [isReadMoreActive, setIsReadMoreActive] = useState(false)
6832 stevensc 398
  const labels = useSelector(({ intl }) => intl.labels)
6618 stevensc 399
 
400
  const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
401
 
6831 stevensc 402
  const htmlParsedText = (fullStringText = '') => {
6618 stevensc 403
    const fullText = parse(fullStringText)
404
    if (fullStringText.length > 500) {
405
      const shortenedString = fullStringText.substr(0, 500)
406
      const shortenedText = parse(`${shortenedString}... `)
407
      return (
408
        <p>
409
          {isReadMoreActive ? fullText : shortenedText}
410
          <span className="cursor-pointer" onClick={readMoreHandler}>
6832 stevensc 411
            {isReadMoreActive ? labels.read_less : labels.read_more}
6618 stevensc 412
          </span>
413
        </p>
414
      )
415
    }
416
    return <p>{fullText}</p>
417
  }
418
 
419
  return (
420
    <div className="shared-post-bar">
421
      <div className="post-bar">
422
        <div className="post_topbar">
423
          <div className="usy-dt">
424
            <img src={image} alt="" style={{ width: '50px', height: 'auto' }} />
425
            <div className="usy-name">
426
              <h3>{name}</h3>
427
              <span>{timeElapse}</span>
428
            </div>
429
          </div>
430
        </div>
431
        <div className="job_descp">
432
          <div className="show-read-more">{htmlParsedText(description)}</div>
6623 stevensc 433
          {image && <img src={image} className="Entradas" loading="lazy" />}
434
          {video && (
435
            <video src={video} controls poster={imagePreview} preload="none" />
6618 stevensc 436
          )}
6623 stevensc 437
          {document && (
438
            <a href={document} target="_blank" rel="noreferrer">
6832 stevensc 439
              {labels.download}
6618 stevensc 440
            </a>
441
          )}
442
        </div>
443
      </div>
444
    </div>
445
  )
446
}
447
 
448
export const FeedHeader = ({
449
  ownerName,
450
  ownerImage,
451
  ownerTimeElapse,
452
  ownerUrl,
453
  feedDeleteUrl,
454
  feedUnique,
455
  feedType,
456
}) => {
457
  const [showConfirmModal, setShowConfirmModal] = useState(false)
458
  const [displayOption, setDisplayOption] = useState(false)
459
  const deleteButton = useRef(null)
460
  const labels = useSelector(({ intl }) => intl.labels)
461
  const dispatch = useDispatch()
462
  useOutsideClick(deleteButton, () => setDisplayOption(false))
463
 
464
  const handleShowConfirmModal = () => {
465
    setShowConfirmModal(!showConfirmModal)
466
  }
467
 
468
  const deleteFeedHandler = () => {
469
    axios.post(feedDeleteUrl).then((res) => {
470
      const { data } = res
471
      if (!data.success) {
472
        dispatch(addNotification({ style: 'danger', msg: data.data }))
473
        return
474
      }
475
      dispatch(addNotification({ style: 'success', msg: data.data }))
476
      handleShowConfirmModal()
477
      dispatch(deleteFeed(feedUnique))
478
    })
479
  }
480
 
481
  return (
482
    <>
483
      <div className="post_topbar">
484
        <div className="usy-dt">
485
          <a href={ownerUrl}>
486
            <img
487
              src={ownerImage}
488
              alt=""
489
              style={{ width: '50px', height: 'auto' }}
490
            />
491
          </a>
492
          <div className="usy-name">
493
            <a href={ownerUrl}>
494
              <h3>{ownerName}</h3>
495
            </a>
496
            <span>
497
              {feedType === 'g' && <GroupsRoundedIcon />}
498
              {ownerTimeElapse}
499
            </span>
500
          </div>
501
        </div>
502
        {feedDeleteUrl && (
503
          <div className="cursor-pointer d-flex align-items-center">
504
            <img
505
              src="/images/icons/options.png"
506
              className="cursor-pointer img-icon options"
507
              onClick={() => setDisplayOption(!displayOption)}
508
            />
509
            <div className={`feed-options ${displayOption ? 'active' : ''}`}>
510
              <ul>
511
                <li>
512
                  <button
513
                    className="option-btn"
514
                    onClick={handleShowConfirmModal}
515
                    ref={deleteButton}
516
                  >
517
                    <i className="fa fa-trash-o mr-1" />
518
                    {labels.delete}
519
                  </button>
520
                </li>
521
              </ul>
522
            </div>
523
            <ConfirmModal
524
              show={showConfirmModal}
525
              onClose={() => handleShowConfirmModal(false)}
526
              onAccept={deleteFeedHandler}
527
              acceptLabel="Aceptar"
528
            />
529
          </div>
530
        )}
531
      </div>
532
    </>
533
  )
534
}
535
 
536
Feed.Shared = FeedShared
537
Feed.Description = FeedDescription
538
Feed.Content = FeedContent
539
Feed.Header = FeedHeader
540
 
541
export default React.memo(Feed)