Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 1048 | Rev 1068 | 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";
13
 
1034 stevensc 14
// Redux actions
15
import { openShareModal } from "../../../redux/share-modal/shareModal.actions";
16
import { addNotification } from "../../../redux/notification/notification.actions";
17
import { deleteFeed } from "../../../redux/feed/feed.actions";
18
 
1048 stevensc 19
const FeedTemplate = ({ feed, owner_shared }) => {
1034 stevensc 20
 
1 www 21
  // Destructuring feed data
22
  const {
23
    feed_unique,
24
    owner_name,
25
    owner_url,
26
    owner_image,
27
    owner_comments,
28
    owner_time_elapse,
29
    owner_description,
30
    owner_file_image,
31
    owner_file_video,
32
    owner_file_document,
33
    owner_file_image_preview,
34
    shared_name,
35
    shared_image,
36
    shared_time_elapse,
37
    shared_description,
38
    shared_file_video,
39
    shared_file_image_preview,
40
    shared_file_image,
41
    shared_file_document,
42
    feed_like_url,
43
    feed_unlike_url,
44
    feed_is_liked,
1048 stevensc 45
    feed_likes,
1 www 46
    feed_share_url,
47
    feed_delete_url,
48
    comments,
49
    comment_add_url,
1040 stevensc 50
  } = feed;
1 www 51
 
1034 stevensc 52
  // react hook form
53
  const { register, handleSubmit, errors } = useForm();
722 steven 54
 
1034 stevensc 55
  const dispatch = useDispatch()
1 www 56
 
1034 stevensc 57
  const [totalComments, setTotalComments] = useState(owner_comments || 0);
1 www 58
  const [feedIsLiked, setFeedIsLiked] = useState(feed_is_liked);
59
  const [commentsState, setCommentsState] = useState(comments);
1034 stevensc 60
  const [sharedState, setSharedState] = useState(owner_shared);
1047 stevensc 61
  const [likesState, setLikesState] = useState(feed_likes);
1 www 62
  const [isReadMoreActive, setIsReadMoreActive] = useState(false);
63
  const [showConfirmModal, setShowConfirmModal] = useState(false);
56 steven 64
  const [show, setShow] = useState(false);
1 www 65
 
1034 stevensc 66
  const handleClose = () => setShow(false);
67
  const handleShow = () => setShow(true);
68
 
69
  useEffect(() => {
70
    setSharedState(owner_shared)
1032 stevensc 71
  }, [owner_shared]);
1030 stevensc 72
 
1 www 73
  const deleteFeedHandler = () => {
1043 stevensc 74
    axios.post(feed_delete_url)
1046 stevensc 75
      .then((res) => {
76
        const { data } = res
1043 stevensc 77
        if (data.success) {
78
          dispatch(deleteFeed(feed_unique));
79
          dispatch(addNotification({
80
            style: "success",
81
            msg: data.data,
82
          }));
83
        } else {
84
          dispatch(addNotification({
85
            style: "danger",
86
            msg: data.data,
87
          }));
88
        }
89
      });
1 www 90
  };
91
 
92
  const handleShowConfirmModal = () => {
93
    setShowConfirmModal(!showConfirmModal);
94
  };
95
 
96
  const handleModalAccept = () => {
97
    deleteFeedHandler();
98
  };
99
 
100
  const likeHandler = (event, likeUrl) => {
101
    event.preventDefault();
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);
1 www 129
        setCommentsState([...commentsState, newComment]);
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) => {
141
    axios
142
      .post(deleteCommentUrl)
143
      .then((res) => {
975 steven 144
        const { success, data, total_comments } = res.data;
1 www 145
        if (success) {
146
          const newCommentsState = commentsState.filter(
147
            (comment) => comment.unique !== commentUnique
148
          );
149
          setCommentsState(newCommentsState);
975 steven 150
          setTotalComments(total_comments);
1 www 151
        } else {
1034 stevensc 152
          dispatch(addNotification({
1 www 153
            style: "danger",
154
            msg: data,
1034 stevensc 155
          }));
1 www 156
        }
157
      })
158
      .catch((error) => {
1034 stevensc 159
        dispatch(addNotification({
1 www 160
          style: "danger",
161
          msg: error.message,
1034 stevensc 162
        }));
1 www 163
      });
164
  };
165
 
166
  const btnShareHandler = (event) => {
167
    event.preventDefault();
1034 stevensc 168
    dispatch(openShareModal(feed_share_url, shareModalTypes.SHARE, feedTypes.DASHBOARD, feed_unique))
1 www 169
  };
170
 
171
  let commentsRender = null;
172
  if (commentsState.length) {
173
    commentsRender = (
174
      <div className={styles.commentSection}>
175
        <div className={`comment-sec comment-sec-${feed_unique}`}>
176
          <ul>
177
            {[...commentsState].reverse().map((commentData) => {
178
              const { unique } = commentData;
179
              return (
180
                <FeedCommentTemplate
181
                  commentData={commentData}
182
                  onDeleteHandler={deleteCommentHandler}
183
                  key={unique}
184
                />
185
              );
186
            })}
187
          </ul>
188
        </div>
189
      </div>
190
    );
191
  }
192
 
1045 stevensc 193
  let likeButton = feedIsLiked
194
    ?
195
    (
196
      <a
197
        href={feed_unlike_url}
198
        id={`btn-unlike-${feed_unique}`}
199
        data-feed-unique={feed_unique}
200
        className="btn-unlike"
201
        onClick={(event) => {
202
          likeHandler(event, feed_unlike_url);
203
        }}
204
      >
205
        <i className="fas fa-heart"></i>
1047 stevensc 206
        {likesState}
1045 stevensc 207
      </a>
208
    ) : (
209
      <a
210
        href={feed_like_url}
211
        id={`btn-like-${feed_unique}`}
212
        data-feed-unique={feed_unique}
213
        className="btn-like"
214
        onClick={(event) => {
215
          likeHandler(event, feed_like_url);
216
        }}
217
      >
218
        <i className="far fa-heart"></i>
1047 stevensc 219
        {likesState}
1045 stevensc 220
      </a>
221
    );
1 www 222
 
223
  const readMoreHandler = (event) => {
224
    event.preventDefault();
225
    setIsReadMoreActive(!isReadMoreActive);
226
  };
227
 
228
  const htmlParsedText = (fullStringText) => {
229
    const fullText = parse(fullStringText);
230
    if (fullStringText.length > 500) {
231
      const shortenedString = fullStringText.substr(0, 500);
232
      const shortenedText = parse(`${shortenedString}... `);
233
      return (
234
        <React.Fragment>
235
          {isReadMoreActive ? fullText : shortenedText}
236
          <a
237
            href="#"
238
            onClick={(e) => {
239
              readMoreHandler(e);
240
            }}
241
          >
242
            {isReadMoreActive ? " Leer menos" : " Leer más"}
243
          </a>
244
        </React.Fragment>
245
      );
246
    } else {
247
      return fullText;
248
    }
249
  };
250
 
251
  let sharedName = null;
252
  if (shared_name) {
253
    sharedName = (
254
      <div className="shared-post-bar">
255
        <div className="post-bar">
256
          <div className="post_topbar">
257
            <div className="usy-dt">
258
              <img
259
                src={shared_image}
260
                alt=""
261
                style={{
262
                  width: "50px",
263
                  height: "auto",
264
                }}
265
              />
266
              <div className="usy-name">
267
                <h3>{shared_name}</h3>
268
                <span>
269
                  <img
270
                    style={{
271
                      width: "12px",
272
                      height: "auto",
273
                    }}
274
                    src="/images/clock.png"
275
                    alt=""
276
                  />
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 ? (
298
              <a href={shared_file_document} target="_blank">
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>
55 steven 310
  const TopBar = () => <div className="post_topbar">
311
    <div className="usy-dt">
312
      <a href={owner_url}>
313
        <img
314
          src={owner_image}
315
          alt=""
316
          style={{
317
            width: "50px",
318
            height: "auto",
319
          }}
320
        />
321
      </a>
322
      <div className="usy-name">
323
        <a href={owner_url}>
324
          <h3>{owner_name}</h3>
325
        </a>
326
        <span>
327
          <img src="/images/clock.png" alt="" />
328
          {owner_time_elapse}
329
          {feed_delete_url ? (
330
            <a
331
              href="#"
332
              className="btn-feed-trash"
333
              data-link={feed_delete_url}
334
              data-feed-unique={feed_unique}
335
              onClick={(e) => {
336
                e.preventDefault();
337
                handleShowConfirmModal();
338
              }}
339
            >
340
              <i className="fa fa-trash"></i>
341
            </a>
342
          ) : null}
343
        </span>
344
      </div>
345
    </div>
346
  </div>
1 www 347
 
1021 stevensc 348
  const Content = ({ showDescription }) => <div className="job_descp">
58 steven 349
    {
350
      !!showDescription && (
59 steven 351
        <OwnerDescription />
58 steven 352
      )
353
    }
354
    {owner_file_image ? (
355
      <img src={owner_file_image} className="Entradas" />
356
    ) : null}
357
    {owner_file_video ? (
358
      <video
359
        src={owner_file_video}
360
        controls
361
        poster={owner_file_image_preview}
362
        preload="none"
363
      />
364
    ) : null}
365
    {owner_file_document ? (
366
      <a href={owner_file_document} target="_blank">
367
        Descargar
368
      </a>
369
    ) : null}
370
    {sharedName}
55 steven 371
  </div>
1 www 372
  return (
373
    <React.Fragment>
56 steven 374
      <Modal
375
        show={show}
376
        onHide={handleClose}
59 steven 377
        dialogClassName="modal-md"
56 steven 378
      >
379
        <div
380
          className="row"
381
        >
382
          <div
383
            className="col-md-8 col-sm-12 col-12"
384
          >
205 steven 385
            <Content
386
              showDescription
387
            />
56 steven 388
          </div>
389
          <div
390
            className="col-md-4 col-sm-12 col-12"
391
          >
392
            <TopBar />
59 steven 393
            <OwnerDescription />
56 steven 394
          </div>
395
        </div>
396
      </Modal>
718 steven 397
      <div className={styles.postContainer} >
58 steven 398
        <TopBar
399
          showDescription
400
        />
718 steven 401
        <div
402
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
403
        >
404
          <Content
405
            showDescription
406
          />
407
        </div>
1 www 408
        <div className="job-status-bar">
409
          <ul className="like-com">
410
            <li>{likeButton}</li>
411
            <li>
412
              <a
413
                href="#"
414
                id={`btn-comments-${feed_unique}`}
415
                className="btn-indicator"
416
              >
722 steven 417
                <i className="fas fa-comments"></i> {totalComments}
1 www 418
              </a>
419
            </li>
420
            <li>
421
              <a
422
                href="#"
423
                id={`btn-share-${feed_unique}`}
424
                className="btn-indicator"
425
              >
1034 stevensc 426
                <i className="fas fa-share"></i> {sharedState}
1 www 427
              </a>
428
            </li>
429
          </ul>
430
          <a
431
            href={feed_share_url}
432
            data-feed-unique={feed_unique}
433
            className="btn-feed-share"
434
            onClick={(e) => {
435
              btnShareHandler(e);
436
            }}
437
          >
438
            <i className="fas fa-share"></i>Compartir
439
          </a>
440
        </div>
441
        {commentsRender}
442
        <div>
443
          <form
444
            className={`form-comment-feed-${feed_unique}`}
445
            data-feed-unique={feed_unique}
446
            onSubmit={handleSubmit(submitCommentHandler)}
447
          >
448
            <div className={styles.feedCommentContainer}>
449
              <input
450
                className={styles.commentInput}
451
                type="text"
452
                name="comment"
453
                id={`comment-${feed_unique}`}
454
                maxLength="256"
455
                placeholder="Escribe un comentario"
456
                ref={register({
457
                  required: {
458
                    value: "true",
459
                    message: "El campo es requerido",
460
                  },
461
                })}
462
              />
463
              <button type="submit" className={styles.submitButton}>
464
                Enviar
465
              </button>{" "}
466
              {/* Falta multilenguaje */}
467
            </div>
468
          </form>
469
          {errors.comment && (
470
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
471
          )}
472
        </div>
473
      </div>
474
      <ConfirmModal
475
        show={showConfirmModal}
476
        onClose={() => {
477
          setShowConfirmModal(false);
478
        }}
479
        onAccept={handleModalAccept}
480
        acceptLabel="Aceptar"
481
      />
482
    </React.Fragment>
483
  );
484
};
485
 
1040 stevensc 486
export default React.memo(FeedTemplate);