Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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