Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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