Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

Rev Autor Línea Nro. Línea
3207 stevensc 1
/* eslint-disable react/prop-types */
1025 stevensc 2
import React, { useEffect, useState } from "react";
1034 stevensc 3
import { useDispatch } from "react-redux";
1 www 4
import { useForm } from "react-hook-form";
5
import FormErrorFeedback from "../../../shared/form-error-feedback/FormErrorFeedback";
6
import FeedCommentTemplate from "./feed-comment/FeedCommentTemplate";
7
import { shareModalTypes } from "../../../redux/share-modal/shareModal.types";
8
import parse from "html-react-parser";
1021 stevensc 9
import { axios } from "../../../utils";
1 www 10
import ConfirmModal from "../../../shared/confirm-modal/ConfirmModal";
57 steven 11
import { Modal } from "react-bootstrap";
1 www 12
import { feedTypes } from "../../../redux/feed/feed.types";
3297 stevensc 13
import { BsHeart, BsHeartFill, BsTrash } from 'react-icons/bs'
2839 stevensc 14
import { RiShareForwardLine } from 'react-icons/ri'
15
import { TbSend } from "react-icons/tb";
3307 stevensc 16
import { BiDotsVerticalRounded, BiMessage, BiShareAlt } from "react-icons/bi";
2838 stevensc 17
import styles from "./feedTemplate.module.scss";
18
import styleFeed from "../share-feed/shareFeed.module.scss";
3466 stevensc 19
import { EmailIcon, EmailShareButton, FacebookIcon, FacebookShareButton, RedditIcon, RedditShareButton, TelegramIcon, TelegramShareButton, TwitterIcon, TwitterShareButton, WhatsappIcon, WhatsappShareButton } from "react-share";
1 www 20
 
1034 stevensc 21
// Redux actions
22
import { openShareModal } from "../../../redux/share-modal/shareModal.actions";
23
import { addNotification } from "../../../redux/notification/notification.actions";
24
import { deleteFeed } from "../../../redux/feed/feed.actions";
3202 stevensc 25
import { useRef } from "react";
3324 stevensc 26
import ExternalShareModal from "./ExternalShareModal";
1034 stevensc 27
 
2837 stevensc 28
const FeedTemplate = ({ feed, owner_shared, image }) => {
1034 stevensc 29
 
1 www 30
  // Destructuring feed data
31
  const {
32
    feed_unique,
33
    owner_name,
34
    owner_url,
35
    owner_image,
36
    owner_time_elapse,
37
    owner_description,
38
    owner_file_image,
39
    owner_file_video,
40
    owner_file_document,
41
    owner_file_image_preview,
42
    shared_name,
43
    shared_image,
44
    shared_time_elapse,
45
    shared_description,
46
    shared_file_video,
47
    shared_file_image_preview,
48
    shared_file_image,
49
    shared_file_document,
2572 stevensc 50
    feed_likes,
1 www 51
    feed_like_url,
52
    feed_unlike_url,
53
    feed_is_liked,
3207 stevensc 54
    feed_highlighted,
1 www 55
    feed_share_url,
56
    feed_delete_url,
57
    comments,
58
    comment_add_url,
3303 stevensc 59
    feed_share_external_url
1040 stevensc 60
  } = feed;
1 www 61
 
1034 stevensc 62
  // react hook form
63
  const { register, handleSubmit, errors } = useForm();
722 steven 64
 
1034 stevensc 65
  const dispatch = useDispatch()
1 www 66
 
1291 stevensc 67
  const [totalComments, setTotalComments] = useState(comments.length || 0);
1 www 68
  const [feedIsLiked, setFeedIsLiked] = useState(feed_is_liked);
69
  const [commentsState, setCommentsState] = useState(comments);
1034 stevensc 70
  const [sharedState, setSharedState] = useState(owner_shared);
1047 stevensc 71
  const [likesState, setLikesState] = useState(feed_likes);
1 www 72
  const [isReadMoreActive, setIsReadMoreActive] = useState(false);
73
  const [showConfirmModal, setShowConfirmModal] = useState(false);
2849 stevensc 74
  const [displayOption, setDisplayOption] = useState(false)
3308 stevensc 75
  const [shareOptions, setShareOptions] = useState(false)
3324 stevensc 76
  const [shareModalProps, setShareModalProps] = useState({
77
    isShow: false,
78
    url: ''
79
  })
56 steven 80
  const [show, setShow] = useState(false);
3202 stevensc 81
  const deleteButton = useRef();
3310 stevensc 82
  const shareContainer = useRef(null);
1 www 83
 
1034 stevensc 84
  const handleClose = () => setShow(false);
85
  const handleShow = () => setShow(true);
86
 
87
  useEffect(() => {
88
    setSharedState(owner_shared)
1032 stevensc 89
  }, [owner_shared]);
1030 stevensc 90
 
3202 stevensc 91
  useEffect(() => {
92
    const handleClickOutside = (event) => {
3207 stevensc 93
      if (deleteButton.current && !deleteButton.current.contains(event.target)) {
94
        setDisplayOption(false)
95
      }
3202 stevensc 96
    }
97
    document.addEventListener("mousedown", handleClickOutside);
98
 
99
    return () => {
3207 stevensc 100
      document.removeEventListener("mousedown", handleClickOutside);
3202 stevensc 101
    };
3207 stevensc 102
  }, [deleteButton]);
3202 stevensc 103
 
3310 stevensc 104
  useEffect(() => {
105
    const handleClickOutside = (event) => {
106
      if (shareContainer.current && !shareContainer.current.contains(event.target)) {
3323 stevensc 107
        setShareOptions(false)
3310 stevensc 108
      }
109
    }
110
    document.addEventListener("mousedown", handleClickOutside);
111
 
112
    return () => {
113
      document.removeEventListener("mousedown", handleClickOutside);
114
    };
115
  }, [shareContainer]);
116
 
1 www 117
  const deleteFeedHandler = () => {
1043 stevensc 118
    axios.post(feed_delete_url)
1046 stevensc 119
      .then((res) => {
120
        const { data } = res
1043 stevensc 121
        if (data.success) {
122
          dispatch(deleteFeed(feed_unique));
123
          dispatch(addNotification({
124
            style: "success",
125
            msg: data.data,
126
          }));
127
        } else {
128
          dispatch(addNotification({
129
            style: "danger",
130
            msg: data.data,
131
          }));
132
        }
133
      });
1 www 134
  };
135
 
136
  const handleShowConfirmModal = () => {
137
    setShowConfirmModal(!showConfirmModal);
138
  };
139
 
1072 stevensc 140
  const likeHandler = (likeUrl) => {
1043 stevensc 141
    axios.post(likeUrl)
1046 stevensc 142
      .then((res) => {
143
        const { success, data } = res.data;
1043 stevensc 144
        if (!success) {
145
          setFeedIsLiked((previousState) => !previousState);
146
          dispatch(addNotification({
147
            style: "danger",
148
            msg: data,
149
          }));
1049 stevensc 150
        } else {
151
          setLikesState(data.likes)
152
          setFeedIsLiked(!feedIsLiked);
1043 stevensc 153
        }
154
      });
1 www 155
  };
156
 
157
  const submitCommentHandler = (data, e) => {
158
    const currentFormData = new FormData();
159
    for (let input in data) {
160
      currentFormData.append(input, data[input]);
161
    }
162
    axios.post(comment_add_url, currentFormData).then((res) => {
163
      const resData = res.data;
164
      const { data, success, total_comments } = resData;
165
      if (success) {
166
        const newComment = data;
722 steven 167
        setTotalComments(total_comments);
1084 stevensc 168
        setCommentsState([newComment, ...commentsState]);
1 www 169
        e.target.reset();
170
      } else {
1034 stevensc 171
        dispatch(addNotification({
1 www 172
          style: "danger",
173
          msg: data,
1034 stevensc 174
        }));
1 www 175
      }
176
    });
177
  };
178
 
179
  const deleteCommentHandler = (commentUnique, deleteCommentUrl) => {
1068 stevensc 180
    axios.post(deleteCommentUrl)
1 www 181
      .then((res) => {
975 steven 182
        const { success, data, total_comments } = res.data;
1 www 183
        if (success) {
184
          const newCommentsState = commentsState.filter(
185
            (comment) => comment.unique !== commentUnique
186
          );
187
          setCommentsState(newCommentsState);
975 steven 188
          setTotalComments(total_comments);
1 www 189
        } else {
1034 stevensc 190
          dispatch(addNotification({
1 www 191
            style: "danger",
192
            msg: data,
1034 stevensc 193
          }));
1 www 194
        }
195
      })
196
      .catch((error) => {
1034 stevensc 197
        dispatch(addNotification({
1 www 198
          style: "danger",
199
          msg: error.message,
1034 stevensc 200
        }));
1 www 201
      });
202
  };
203
 
1084 stevensc 204
  const btnShareHandler = () => {
1034 stevensc 205
    dispatch(openShareModal(feed_share_url, shareModalTypes.SHARE, feedTypes.DASHBOARD, feed_unique))
1 www 206
  };
207
 
208
  let commentsRender = null;
209
  if (commentsState.length) {
210
    commentsRender = (
211
      <div className={styles.commentSection}>
212
        <div className={`comment-sec comment-sec-${feed_unique}`}>
213
          <ul>
214
            {[...commentsState].reverse().map((commentData) => {
215
              const { unique } = commentData;
216
              return (
217
                <FeedCommentTemplate
218
                  commentData={commentData}
219
                  onDeleteHandler={deleteCommentHandler}
220
                  key={unique}
221
                />
222
              );
223
            })}
224
          </ul>
225
        </div>
226
      </div>
227
    );
228
  }
229
 
230
  const readMoreHandler = (event) => {
231
    event.preventDefault();
232
    setIsReadMoreActive(!isReadMoreActive);
233
  };
234
 
235
  const htmlParsedText = (fullStringText) => {
236
    const fullText = parse(fullStringText);
237
    if (fullStringText.length > 500) {
238
      const shortenedString = fullStringText.substr(0, 500);
239
      const shortenedText = parse(`${shortenedString}... `);
240
      return (
241
        <React.Fragment>
242
          {isReadMoreActive ? fullText : shortenedText}
243
          <a
244
            href="#"
245
            onClick={(e) => {
246
              readMoreHandler(e);
247
            }}
248
          >
249
            {isReadMoreActive ? " Leer menos" : " Leer más"}
250
          </a>
251
        </React.Fragment>
252
      );
253
    } else {
254
      return fullText;
255
    }
256
  };
257
 
258
  let sharedName = null;
259
  if (shared_name) {
260
    sharedName = (
261
      <div className="shared-post-bar">
262
        <div className="post-bar">
263
          <div className="post_topbar">
264
            <div className="usy-dt">
265
              <img
266
                src={shared_image}
267
                alt=""
268
                style={{
269
                  width: "50px",
270
                  height: "auto",
271
                }}
272
              />
273
              <div className="usy-name">
274
                <h3>{shared_name}</h3>
275
                <span>
276
                  {shared_time_elapse}
277
                </span>
278
              </div>
279
            </div>
280
          </div>
281
          <div className="job_descp">
282
            <div className="show-read-more">
283
              {htmlParsedText(shared_description)}
284
            </div>
285
            {shared_file_image ? (
286
              <img src={shared_file_image} className="Entradas" />
287
            ) : null}
288
            {shared_file_video ? (
289
              <video
290
                src={shared_file_video}
291
                controls
292
                poster={shared_file_image_preview}
293
                preload="none"
294
              />
295
            ) : null}
296
            {shared_file_document ? (
3202 stevensc 297
              <a href={shared_file_document} target="_blank" rel="noreferrer">
1 www 298
                Descargar
299
              </a>
300
            ) : null}
301
          </div>
302
        </div>
303
      </div>
304
    );
305
  }
59 steven 306
  const OwnerDescription = () => <div className="show-read-more">
307
    {htmlParsedText(owner_description)}
308
  </div>
3202 stevensc 309
 
1084 stevensc 310
  const TopBar = () => (
2849 stevensc 311
    < div className="post_topbar" >
1084 stevensc 312
      <div className="usy-dt">
313
        <a href={owner_url}>
314
          <img src={owner_image} alt="" style={{
55 steven 315
            width: "50px",
316
            height: "auto",
317
          }}
1084 stevensc 318
          />
55 steven 319
        </a>
3478 stevensc 320
        <div className="usy-name ">
1084 stevensc 321
          <a href={owner_url}>
3478 stevensc 322
            <h3 className="main-text">{owner_name}</h3>
1084 stevensc 323
          </a>
324
          <span>
325
            {owner_time_elapse}
326
          </span>
327
        </div>
55 steven 328
      </div>
2852 stevensc 329
      {
330
        feed_delete_url
331
        &&
2853 stevensc 332
        <div className="cursor-pointer d-flex align-items-center">
333
          <BiDotsVerticalRounded
334
            onClick={() => setDisplayOption(!displayOption)}
335
            style={{ fontSize: '1.5rem' }}
336
          />
2852 stevensc 337
          <div className={`feed-options ${displayOption ? 'active' : ''}`}>
338
            <ul>
339
              <li>
340
                <button
341
                  className="option-btn"
342
                  onClick={handleShowConfirmModal}
3202 stevensc 343
                  ref={deleteButton}
2852 stevensc 344
                >
345
                  <BsTrash className="mr-1" />
2974 stevensc 346
                  Borrar
2852 stevensc 347
                </button>
348
              </li>
349
            </ul>
350
          </div>
2849 stevensc 351
        </div>
2852 stevensc 352
      }
1084 stevensc 353
    </div >
354
  )
1 www 355
 
1079 stevensc 356
  const Content = ({ showDescription }) => (
357
    <div className="job_descp">
358
      {
359
        showDescription
360
        &&
59 steven 361
        <OwnerDescription />
1079 stevensc 362
      }
363
      {
364
        owner_file_image
365
        &&
366
        <img src={owner_file_image} className="Entradas" />
367
      }
368
      {
369
        owner_file_video
370
        &&
371
        <video
372
          src={owner_file_video}
373
          controls
374
          poster={owner_file_image_preview}
375
          preload="none"
376
        />
377
      }
378
      {
379
        owner_file_document
380
        &&
3202 stevensc 381
        <a href={owner_file_document} target="_blank" rel="noreferrer">
1079 stevensc 382
          Descargar
383
        </a>
384
      }
385
      {sharedName}
386
    </div>
387
  )
1 www 388
  return (
389
    <React.Fragment>
56 steven 390
      <Modal
391
        show={show}
392
        onHide={handleClose}
3203 stevensc 393
        dialogClassName="modal-lg"
56 steven 394
      >
395
        <div
396
          className="row"
397
        >
398
          <div
399
            className="col-md-8 col-sm-12 col-12"
400
          >
205 steven 401
            <Content
402
              showDescription
403
            />
56 steven 404
          </div>
405
          <div
406
            className="col-md-4 col-sm-12 col-12"
407
          >
408
            <TopBar />
59 steven 409
            <OwnerDescription />
56 steven 410
          </div>
411
        </div>
412
      </Modal>
3324 stevensc 413
      <ExternalShareModal
414
        url={shareModalProps.url}
415
        isShow={shareModalProps.isShow}
416
        closeModal={() => setShareModalProps(prev => ({ ...prev, isShow: false }))}
417
      />
3207 stevensc 418
      <div className={`${styles.postContainer} ${feed_highlighted ? 'highlighted' : ''}`}>
58 steven 419
        <TopBar
420
          showDescription
421
        />
718 steven 422
        <div
423
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
424
        >
425
          <Content
426
            showDescription
427
          />
428
        </div>
1 www 429
        <div className="job-status-bar">
2833 stevensc 430
          <ul className="reactions-list">
1 www 431
            <li>
1082 stevensc 432
              <button
433
                type="button"
434
                id={feedIsLiked ? `btn-unlike-${feed_unique}` : `btn-like-${feed_unique}`}
435
                data-feed-unique={feed_unique}
436
                className={feedIsLiked ? "btn-unlike" : "btn-like"}
3202 stevensc 437
                onClick={() => likeHandler(feedIsLiked ? feed_unlike_url : feed_like_url)}
1082 stevensc 438
              >
2836 stevensc 439
                {feedIsLiked ? <BsHeartFill className="mr-1" /> : <BsHeart className="mr-1" />}
2571 stevensc 440
                {likesState}
1082 stevensc 441
              </button>
1068 stevensc 442
            </li>
443
            <li>
1080 stevensc 444
              <button
445
                type="button"
1 www 446
                id={`btn-comments-${feed_unique}`}
447
                className="btn-indicator"
448
              >
2839 stevensc 449
                <BiMessage className="mr-1" />
2571 stevensc 450
                {totalComments}
1080 stevensc 451
              </button>
1 www 452
            </li>
453
            <li>
1080 stevensc 454
              <button
455
                type="button"
1 www 456
                id={`btn-share-${feed_unique}`}
457
                className="btn-indicator"
2211 stevensc 458
                onClick={btnShareHandler}
459
              >
2839 stevensc 460
                <RiShareForwardLine className="mr-1" />
2571 stevensc 461
                {sharedState}
2211 stevensc 462
              </button>
463
            </li>
3307 stevensc 464
            <li className="position-relative">
465
              <button
466
                type="button"
467
                className="btn-indicator"
3354 stevensc 468
                onClick={() => setShareOptions(!shareOptions)}
3305 stevensc 469
              >
3307 stevensc 470
                <BiShareAlt />
471
              </button>
3308 stevensc 472
              {
473
                shareOptions &&
3310 stevensc 474
                <div className="ext_share" ref={shareContainer}>
3384 stevensc 475
                  <FacebookShareButton url={feed_share_external_url}>
3308 stevensc 476
                    <FacebookIcon size={32} round />
477
                  </FacebookShareButton>
3384 stevensc 478
                  <TwitterShareButton url={feed_share_external_url}>
3309 stevensc 479
                    <TwitterIcon size={32} round />
480
                  </TwitterShareButton>
3384 stevensc 481
                  <TelegramShareButton url={feed_share_external_url}>
3309 stevensc 482
                    <TelegramIcon size={32} round />
483
                  </TelegramShareButton>
3384 stevensc 484
                  <WhatsappShareButton url={feed_share_external_url}>
3309 stevensc 485
                    <WhatsappIcon size={32} round />
486
                  </WhatsappShareButton>
3384 stevensc 487
                  <RedditShareButton url={feed_share_external_url}>
3309 stevensc 488
                    <RedditIcon size={32} round />
489
                  </RedditShareButton>
3384 stevensc 490
                  <EmailShareButton url={feed_share_external_url}>
3309 stevensc 491
                    <EmailIcon size={32} round />
492
                  </EmailShareButton>
3308 stevensc 493
                </div>
494
              }
3303 stevensc 495
            </li>
1 www 496
          </ul>
497
        </div>
498
        {commentsRender}
499
        <div>
500
          <form
501
            className={`form-comment-feed-${feed_unique}`}
502
            data-feed-unique={feed_unique}
503
            onSubmit={handleSubmit(submitCommentHandler)}
504
          >
505
            <div className={styles.feedCommentContainer}>
2837 stevensc 506
              <img src={image} alt="User profile image" />
1 www 507
              <input
508
                className={styles.commentInput}
509
                type="text"
510
                name="comment"
511
                id={`comment-${feed_unique}`}
512
                maxLength="256"
513
                placeholder="Escribe un comentario"
514
                ref={register({
515
                  required: {
516
                    value: "true",
517
                    message: "El campo es requerido",
518
                  },
519
                })}
520
              />
2838 stevensc 521
              <button className={`${styleFeed.shareIconContainer} ${styleFeed.iconActive}`} >
522
                <TbSend className={styleFeed.shareIcon} />
1084 stevensc 523
              </button>
1 www 524
            </div>
525
          </form>
1084 stevensc 526
          {
527
            errors.comment
528
            &&
1 www 529
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
1084 stevensc 530
          }
1 www 531
        </div>
532
      </div>
533
      <ConfirmModal
534
        show={showConfirmModal}
1084 stevensc 535
        onClose={() => setShowConfirmModal(false)}
536
        onAccept={deleteFeedHandler}
1 www 537
        acceptLabel="Aceptar"
538
      />
539
    </React.Fragment>
540
  );
541
};
542
 
1040 stevensc 543
export default React.memo(FeedTemplate);