Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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