Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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