Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 1047 | Rev 1049 | 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();
102
    setFeedIsLiked(!feedIsLiked);
1043 stevensc 103
    axios.post(likeUrl)
1046 stevensc 104
      .then((res) => {
105
        const { success, data } = res.data;
1043 stevensc 106
        if (!success) {
107
          setFeedIsLiked((previousState) => !previousState);
108
          dispatch(addNotification({
109
            style: "danger",
110
            msg: data,
111
          }));
112
        }
1047 stevensc 113
        setLikesState(data.likes)
1043 stevensc 114
      });
1 www 115
  };
116
 
117
  const submitCommentHandler = (data, e) => {
118
    const currentFormData = new FormData();
119
    for (let input in data) {
120
      currentFormData.append(input, data[input]);
121
    }
122
    axios.post(comment_add_url, currentFormData).then((res) => {
123
      const resData = res.data;
124
      const { data, success, total_comments } = resData;
125
      if (success) {
126
        const newComment = data;
722 steven 127
        setTotalComments(total_comments);
1 www 128
        setCommentsState([...commentsState, newComment]);
129
        e.target.reset();
130
      } else {
1034 stevensc 131
        dispatch(addNotification({
1 www 132
          style: "danger",
133
          msg: data,
1034 stevensc 134
        }));
1 www 135
      }
136
    });
137
  };
138
 
139
  const deleteCommentHandler = (commentUnique, deleteCommentUrl) => {
140
    axios
141
      .post(deleteCommentUrl)
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
 
165
  const btnShareHandler = (event) => {
166
    event.preventDefault();
1034 stevensc 167
    dispatch(openShareModal(feed_share_url, shareModalTypes.SHARE, feedTypes.DASHBOARD, feed_unique))
1 www 168
  };
169
 
170
  let commentsRender = null;
171
  if (commentsState.length) {
172
    commentsRender = (
173
      <div className={styles.commentSection}>
174
        <div className={`comment-sec comment-sec-${feed_unique}`}>
175
          <ul>
176
            {[...commentsState].reverse().map((commentData) => {
177
              const { unique } = commentData;
178
              return (
179
                <FeedCommentTemplate
180
                  commentData={commentData}
181
                  onDeleteHandler={deleteCommentHandler}
182
                  key={unique}
183
                />
184
              );
185
            })}
186
          </ul>
187
        </div>
188
      </div>
189
    );
190
  }
191
 
1045 stevensc 192
  let likeButton = feedIsLiked
193
    ?
194
    (
195
      <a
196
        href={feed_unlike_url}
197
        id={`btn-unlike-${feed_unique}`}
198
        data-feed-unique={feed_unique}
199
        className="btn-unlike"
200
        onClick={(event) => {
201
          likeHandler(event, feed_unlike_url);
202
        }}
203
      >
204
        <i className="fas fa-heart"></i>
1047 stevensc 205
        {likesState}
1045 stevensc 206
      </a>
207
    ) : (
208
      <a
209
        href={feed_like_url}
210
        id={`btn-like-${feed_unique}`}
211
        data-feed-unique={feed_unique}
212
        className="btn-like"
213
        onClick={(event) => {
214
          likeHandler(event, feed_like_url);
215
        }}
216
      >
217
        <i className="far fa-heart"></i>
1047 stevensc 218
        {likesState}
1045 stevensc 219
      </a>
220
    );
1 www 221
 
222
  const readMoreHandler = (event) => {
223
    event.preventDefault();
224
    setIsReadMoreActive(!isReadMoreActive);
225
  };
226
 
227
  const htmlParsedText = (fullStringText) => {
228
    const fullText = parse(fullStringText);
229
    if (fullStringText.length > 500) {
230
      const shortenedString = fullStringText.substr(0, 500);
231
      const shortenedText = parse(`${shortenedString}... `);
232
      return (
233
        <React.Fragment>
234
          {isReadMoreActive ? fullText : shortenedText}
235
          <a
236
            href="#"
237
            onClick={(e) => {
238
              readMoreHandler(e);
239
            }}
240
          >
241
            {isReadMoreActive ? " Leer menos" : " Leer más"}
242
          </a>
243
        </React.Fragment>
244
      );
245
    } else {
246
      return fullText;
247
    }
248
  };
249
 
250
  let sharedName = null;
251
  if (shared_name) {
252
    sharedName = (
253
      <div className="shared-post-bar">
254
        <div className="post-bar">
255
          <div className="post_topbar">
256
            <div className="usy-dt">
257
              <img
258
                src={shared_image}
259
                alt=""
260
                style={{
261
                  width: "50px",
262
                  height: "auto",
263
                }}
264
              />
265
              <div className="usy-name">
266
                <h3>{shared_name}</h3>
267
                <span>
268
                  <img
269
                    style={{
270
                      width: "12px",
271
                      height: "auto",
272
                    }}
273
                    src="/images/clock.png"
274
                    alt=""
275
                  />
276
                  {shared_time_elapse}
277
                </span>
278
              </div>
279
            </div>
280
          </div>
281
          <div className="job_descp">
282
            <div className="show-read-more">
283
              {htmlParsedText(shared_description)}
284
            </div>
285
            {shared_file_image ? (
286
              <img src={shared_file_image} className="Entradas" />
287
            ) : null}
288
            {shared_file_video ? (
289
              <video
290
                src={shared_file_video}
291
                controls
292
                poster={shared_file_image_preview}
293
                preload="none"
294
              />
295
            ) : null}
296
            {shared_file_document ? (
297
              <a href={shared_file_document} target="_blank">
298
                Descargar
299
              </a>
300
            ) : null}
301
          </div>
302
        </div>
303
      </div>
304
    );
305
  }
59 steven 306
  const OwnerDescription = () => <div className="show-read-more">
307
    {htmlParsedText(owner_description)}
308
  </div>
55 steven 309
  const TopBar = () => <div className="post_topbar">
310
    <div className="usy-dt">
311
      <a href={owner_url}>
312
        <img
313
          src={owner_image}
314
          alt=""
315
          style={{
316
            width: "50px",
317
            height: "auto",
318
          }}
319
        />
320
      </a>
321
      <div className="usy-name">
322
        <a href={owner_url}>
323
          <h3>{owner_name}</h3>
324
        </a>
325
        <span>
326
          <img src="/images/clock.png" alt="" />
327
          {owner_time_elapse}
328
          {feed_delete_url ? (
329
            <a
330
              href="#"
331
              className="btn-feed-trash"
332
              data-link={feed_delete_url}
333
              data-feed-unique={feed_unique}
334
              onClick={(e) => {
335
                e.preventDefault();
336
                handleShowConfirmModal();
337
              }}
338
            >
339
              <i className="fa fa-trash"></i>
340
            </a>
341
          ) : null}
342
        </span>
343
      </div>
344
    </div>
345
  </div>
1 www 346
 
1021 stevensc 347
  const Content = ({ showDescription }) => <div className="job_descp">
58 steven 348
    {
349
      !!showDescription && (
59 steven 350
        <OwnerDescription />
58 steven 351
      )
352
    }
353
    {owner_file_image ? (
354
      <img src={owner_file_image} className="Entradas" />
355
    ) : null}
356
    {owner_file_video ? (
357
      <video
358
        src={owner_file_video}
359
        controls
360
        poster={owner_file_image_preview}
361
        preload="none"
362
      />
363
    ) : null}
364
    {owner_file_document ? (
365
      <a href={owner_file_document} target="_blank">
366
        Descargar
367
      </a>
368
    ) : null}
369
    {sharedName}
55 steven 370
  </div>
1 www 371
  return (
372
    <React.Fragment>
56 steven 373
      <Modal
374
        show={show}
375
        onHide={handleClose}
59 steven 376
        dialogClassName="modal-md"
56 steven 377
      >
378
        <div
379
          className="row"
380
        >
381
          <div
382
            className="col-md-8 col-sm-12 col-12"
383
          >
205 steven 384
            <Content
385
              showDescription
386
            />
56 steven 387
          </div>
388
          <div
389
            className="col-md-4 col-sm-12 col-12"
390
          >
391
            <TopBar />
59 steven 392
            <OwnerDescription />
56 steven 393
          </div>
394
        </div>
395
      </Modal>
718 steven 396
      <div className={styles.postContainer} >
58 steven 397
        <TopBar
398
          showDescription
399
        />
718 steven 400
        <div
401
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
402
        >
403
          <Content
404
            showDescription
405
          />
406
        </div>
1 www 407
        <div className="job-status-bar">
408
          <ul className="like-com">
409
            <li>{likeButton}</li>
410
            <li>
411
              <a
412
                href="#"
413
                id={`btn-comments-${feed_unique}`}
414
                className="btn-indicator"
415
              >
722 steven 416
                <i className="fas fa-comments"></i> {totalComments}
1 www 417
              </a>
418
            </li>
419
            <li>
420
              <a
421
                href="#"
422
                id={`btn-share-${feed_unique}`}
423
                className="btn-indicator"
424
              >
1034 stevensc 425
                <i className="fas fa-share"></i> {sharedState}
1 www 426
              </a>
427
            </li>
428
          </ul>
429
          <a
430
            href={feed_share_url}
431
            data-feed-unique={feed_unique}
432
            className="btn-feed-share"
433
            onClick={(e) => {
434
              btnShareHandler(e);
435
            }}
436
          >
437
            <i className="fas fa-share"></i>Compartir
438
          </a>
439
        </div>
440
        {commentsRender}
441
        <div>
442
          <form
443
            className={`form-comment-feed-${feed_unique}`}
444
            data-feed-unique={feed_unique}
445
            onSubmit={handleSubmit(submitCommentHandler)}
446
          >
447
            <div className={styles.feedCommentContainer}>
448
              <input
449
                className={styles.commentInput}
450
                type="text"
451
                name="comment"
452
                id={`comment-${feed_unique}`}
453
                maxLength="256"
454
                placeholder="Escribe un comentario"
455
                ref={register({
456
                  required: {
457
                    value: "true",
458
                    message: "El campo es requerido",
459
                  },
460
                })}
461
              />
462
              <button type="submit" className={styles.submitButton}>
463
                Enviar
464
              </button>{" "}
465
              {/* Falta multilenguaje */}
466
            </div>
467
          </form>
468
          {errors.comment && (
469
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
470
          )}
471
        </div>
472
      </div>
473
      <ConfirmModal
474
        show={showConfirmModal}
475
        onClose={() => {
476
          setShowConfirmModal(false);
477
        }}
478
        onAccept={handleModalAccept}
479
        acceptLabel="Aceptar"
480
      />
481
    </React.Fragment>
482
  );
483
};
484
 
1040 stevensc 485
export default React.memo(FeedTemplate);