Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

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