Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

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