Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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