Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 1030 | Rev 1032 | 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";
1 www 2
import { connect } from "react-redux";
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 { openShareModal as OpenShareModalAction } from "../../../redux/share-modal/shareModal.actions";
7
import { addNotification } from "../../../redux/notification/notification.actions";
8
import { deleteFeed } from "../../../redux/feed/feed.actions";
9
import { shareModalTypes } from "../../../redux/share-modal/shareModal.types";
10
import parse from "html-react-parser";
1021 stevensc 11
import { axios } from "../../../utils";
1 www 12
import ConfirmModal from "../../../shared/confirm-modal/ConfirmModal";
57 steven 13
import { Modal } from "react-bootstrap";
1 www 14
import styles from "./feedTemplate.module.scss";
15
import { feedTypes } from "../../../redux/feed/feed.types";
16
 
17
const FeedTemplate = (props) => {
18
  // Destructuring feed data
1031 stevensc 19
 
20
  const feed = {...props.feed}
1 www 21
  const {
22
    feed_unique,
23
    feed_id_encrypted,
24
    owner_name,
25
    owner_url,
26
    owner_image,
27
    owner_comments,
28
    owner_shared,
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,
43
    feed_like_url,
44
    feed_unlike_url,
45
    feed_is_liked,
46
    feed_share_url,
47
    feed_delete_url,
48
    comments,
49
    comment_add_url,
1031 stevensc 50
  } = feed;
1 www 51
 
722 steven 52
  const [totalComments, setTotalComments] = useState(owner_comments || 0);
53
 
1 www 54
  // Destructuring redux
55
  const { feedType } = props;
56
  const { deleteFeed, addNotification, openShareModal } = props;
57
 
58
  const [feedIsLiked, setFeedIsLiked] = useState(feed_is_liked);
59
 
60
  // react hook form
61
  const { register, handleSubmit, errors } = useForm();
62
 
63
  const [commentsState, setCommentsState] = useState(comments);
1023 stevensc 64
  const [ownerShared, setOwnerShared] = useState(owner_shared);
1 www 65
 
66
  const [isReadMoreActive, setIsReadMoreActive] = useState(false);
67
  const [showConfirmModal, setShowConfirmModal] = useState(false);
56 steven 68
  const [show, setShow] = useState(false);
1 www 69
 
1031 stevensc 70
  useEffect(() => {
71
    setOwnerShared(owner_shared)
72
  }, [feed.owner_shared]);
1030 stevensc 73
 
56 steven 74
  const handleClose = () => setShow(false);
75
  const handleShow = () => setShow(true);
1 www 76
  const deleteFeedHandler = () => {
77
    axios.post(feed_delete_url).then((res) => {
78
      const data = res.data;
79
      if (data.success) {
80
        deleteFeed(feed_unique);
81
        addNotification({
82
          style: "success",
83
          msg: data.data,
84
        });
85
      } else {
86
        addNotification({
87
          style: "danger",
88
          msg: data.data,
89
        });
90
      }
91
    });
92
  };
93
 
94
  const handleShowConfirmModal = () => {
95
    setShowConfirmModal(!showConfirmModal);
96
  };
97
 
98
  const handleModalAccept = () => {
99
    deleteFeedHandler();
100
  };
101
 
102
  const likeHandler = (event, likeUrl) => {
103
    event.preventDefault();
104
    setFeedIsLiked(!feedIsLiked);
105
    axios.post(likeUrl).then((res) => {
106
      const resData = res.data;
107
      const { success, data } = resData;
108
      if (!success) {
109
        setFeedIsLiked((previousState) => !previousState);
110
        addNotification({
111
          style: "danger",
112
          msg: data,
113
        });
114
      }
115
    });
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 {
132
        addNotification({
133
          style: "danger",
134
          msg: data,
135
        });
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 {
152
          addNotification({
153
            style: "danger",
154
            msg: data,
155
          });
156
        }
157
      })
158
      .catch((error) => {
159
        addNotification({
160
          style: "danger",
161
          msg: error.message,
162
        });
163
      });
164
  };
165
 
166
  const btnShareHandler = (event) => {
167
    event.preventDefault();
1018 stevensc 168
    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
 
193
  let likeButton = feedIsLiked ? (
194
    <a
195
      href={feed_unlike_url}
196
      id={`btn-unlike-${feed_unique}`}
197
      data-feed-unique={feed_unique}
198
      className="btn-unlike"
199
      onClick={(event) => {
200
        likeHandler(event, feed_unlike_url);
201
      }}
202
    >
203
      <i className="fas fa-heart"></i>
204
      Ya no me gusta
205
    </a>
206
  ) : (
207
    <a
208
      href={feed_like_url}
209
      id={`btn-like-${feed_unique}`}
210
      data-feed-unique={feed_unique}
211
      className="btn-like"
212
      onClick={(event) => {
213
        likeHandler(event, feed_like_url);
214
      }}
215
    >
216
      <i className="far fa-heart"></i>
217
      Me gusta
218
    </a>
219
  );
220
 
221
  const readMoreHandler = (event) => {
222
    event.preventDefault();
223
    setIsReadMoreActive(!isReadMoreActive);
224
  };
225
 
226
  const htmlParsedText = (fullStringText) => {
227
    const fullText = parse(fullStringText);
228
    if (fullStringText.length > 500) {
229
      const shortenedString = fullStringText.substr(0, 500);
230
      const shortenedText = parse(`${shortenedString}... `);
231
      return (
232
        <React.Fragment>
233
          {isReadMoreActive ? fullText : shortenedText}
234
          <a
235
            href="#"
236
            onClick={(e) => {
237
              readMoreHandler(e);
238
            }}
239
          >
240
            {isReadMoreActive ? " Leer menos" : " Leer más"}
241
          </a>
242
        </React.Fragment>
243
      );
244
    } else {
245
      return fullText;
246
    }
247
  };
248
 
249
  let sharedName = null;
250
  if (shared_name) {
251
    sharedName = (
252
      <div className="shared-post-bar">
253
        <div className="post-bar">
254
          <div className="post_topbar">
255
            <div className="usy-dt">
256
              <img
257
                src={shared_image}
258
                alt=""
259
                style={{
260
                  width: "50px",
261
                  height: "auto",
262
                }}
263
              />
264
              <div className="usy-name">
265
                <h3>{shared_name}</h3>
266
                <span>
267
                  <img
268
                    style={{
269
                      width: "12px",
270
                      height: "auto",
271
                    }}
272
                    src="/images/clock.png"
273
                    alt=""
274
                  />
275
                  {shared_time_elapse}
276
                </span>
277
              </div>
278
            </div>
279
          </div>
280
          <div className="job_descp">
281
            <div className="show-read-more">
282
              {htmlParsedText(shared_description)}
283
            </div>
284
            {shared_file_image ? (
285
              <img src={shared_file_image} className="Entradas" />
286
            ) : null}
287
            {shared_file_video ? (
288
              <video
289
                src={shared_file_video}
290
                controls
291
                poster={shared_file_image_preview}
292
                preload="none"
293
              />
294
            ) : null}
295
            {shared_file_document ? (
296
              <a href={shared_file_document} target="_blank">
297
                Descargar
298
              </a>
299
            ) : null}
300
          </div>
301
        </div>
302
      </div>
303
    );
304
  }
59 steven 305
  const OwnerDescription = () => <div className="show-read-more">
306
    {htmlParsedText(owner_description)}
307
  </div>
55 steven 308
  const TopBar = () => <div className="post_topbar">
309
    <div className="usy-dt">
310
      <a href={owner_url}>
311
        <img
312
          src={owner_image}
313
          alt=""
314
          style={{
315
            width: "50px",
316
            height: "auto",
317
          }}
318
        />
319
      </a>
320
      <div className="usy-name">
321
        <a href={owner_url}>
322
          <h3>{owner_name}</h3>
323
        </a>
324
        <span>
325
          <img src="/images/clock.png" alt="" />
326
          {owner_time_elapse}
327
          {feed_delete_url ? (
328
            <a
329
              href="#"
330
              className="btn-feed-trash"
331
              data-link={feed_delete_url}
332
              data-feed-unique={feed_unique}
333
              onClick={(e) => {
334
                e.preventDefault();
335
                handleShowConfirmModal();
336
              }}
337
            >
338
              <i className="fa fa-trash"></i>
339
            </a>
340
          ) : null}
341
        </span>
342
      </div>
343
    </div>
344
  </div>
1 www 345
 
1021 stevensc 346
  const Content = ({ showDescription }) => <div className="job_descp">
58 steven 347
    {
348
      !!showDescription && (
59 steven 349
        <OwnerDescription />
58 steven 350
      )
351
    }
352
    {owner_file_image ? (
353
      <img src={owner_file_image} className="Entradas" />
354
    ) : null}
355
    {owner_file_video ? (
356
      <video
357
        src={owner_file_video}
358
        controls
359
        poster={owner_file_image_preview}
360
        preload="none"
361
      />
362
    ) : null}
363
    {owner_file_document ? (
364
      <a href={owner_file_document} target="_blank">
365
        Descargar
366
      </a>
367
    ) : null}
368
    {sharedName}
55 steven 369
  </div>
1 www 370
  return (
371
    <React.Fragment>
56 steven 372
      <Modal
373
        show={show}
374
        onHide={handleClose}
59 steven 375
        dialogClassName="modal-md"
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>
718 steven 395
      <div className={styles.postContainer} >
58 steven 396
        <TopBar
397
          showDescription
398
        />
718 steven 399
        <div
400
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
401
        >
402
          <Content
403
            showDescription
404
          />
405
        </div>
1 www 406
        <div className="job-status-bar">
407
          <ul className="like-com">
408
            <li>{likeButton}</li>
409
            <li>
410
              <a
411
                href="#"
412
                id={`btn-comments-${feed_unique}`}
413
                className="btn-indicator"
414
              >
722 steven 415
                <i className="fas fa-comments"></i> {totalComments}
1 www 416
              </a>
417
            </li>
418
            <li>
419
              <a
420
                href="#"
421
                id={`btn-share-${feed_unique}`}
422
                className="btn-indicator"
423
              >
1023 stevensc 424
                <i className="fas fa-share"></i> {ownerShared}
1 www 425
              </a>
426
            </li>
427
          </ul>
428
          <a
429
            href={feed_share_url}
430
            data-feed-unique={feed_unique}
431
            className="btn-feed-share"
432
            onClick={(e) => {
433
              btnShareHandler(e);
434
            }}
435
          >
436
            <i className="fas fa-share"></i>Compartir
437
          </a>
438
        </div>
439
        {commentsRender}
440
        <div>
441
          <form
442
            className={`form-comment-feed-${feed_unique}`}
443
            data-feed-unique={feed_unique}
444
            onSubmit={handleSubmit(submitCommentHandler)}
445
          >
446
            <div className={styles.feedCommentContainer}>
447
              <input
448
                className={styles.commentInput}
449
                type="text"
450
                name="comment"
451
                id={`comment-${feed_unique}`}
452
                maxLength="256"
453
                placeholder="Escribe un comentario"
454
                ref={register({
455
                  required: {
456
                    value: "true",
457
                    message: "El campo es requerido",
458
                  },
459
                })}
460
              />
461
              <button type="submit" className={styles.submitButton}>
462
                Enviar
463
              </button>{" "}
464
              {/* Falta multilenguaje */}
465
            </div>
466
          </form>
467
          {errors.comment && (
468
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
469
          )}
470
        </div>
471
      </div>
472
      <ConfirmModal
473
        show={showConfirmModal}
474
        onClose={() => {
475
          setShowConfirmModal(false);
476
        }}
477
        onAccept={handleModalAccept}
478
        acceptLabel="Aceptar"
479
      />
480
    </React.Fragment>
481
  );
482
};
483
 
484
const mapStateToProps = (state) => ({
485
  currentFeed: state.feed.currentFeed,
486
  isShareModalOpen: state.feed.isShareModalOpen,
487
  feedType: state.shareModal.feedType,
488
});
489
 
490
const mapDispatchToProps = {
491
  deleteFeed: (feedId) => deleteFeed(feedId),
1021 stevensc 492
  openShareModal: (postUrl, modalType, feedType, feed_unique) => OpenShareModalAction(postUrl, modalType, feedType, feed_unique),
1 www 493
  addNotification: (notification) => addNotification(notification),
494
};
495
 
496
export default connect(mapStateToProps, mapDispatchToProps)(FeedTemplate);