Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

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