Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 1049 | Rev 1072 | 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) => {
1068 stevensc 141
    axios.post(deleteCommentUrl)
1 www 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
 
192
  const readMoreHandler = (event) => {
193
    event.preventDefault();
194
    setIsReadMoreActive(!isReadMoreActive);
195
  };
196
 
197
  const htmlParsedText = (fullStringText) => {
198
    const fullText = parse(fullStringText);
199
    if (fullStringText.length > 500) {
200
      const shortenedString = fullStringText.substr(0, 500);
201
      const shortenedText = parse(`${shortenedString}... `);
202
      return (
203
        <React.Fragment>
204
          {isReadMoreActive ? fullText : shortenedText}
205
          <a
206
            href="#"
207
            onClick={(e) => {
208
              readMoreHandler(e);
209
            }}
210
          >
211
            {isReadMoreActive ? " Leer menos" : " Leer más"}
212
          </a>
213
        </React.Fragment>
214
      );
215
    } else {
216
      return fullText;
217
    }
218
  };
219
 
220
  let sharedName = null;
221
  if (shared_name) {
222
    sharedName = (
223
      <div className="shared-post-bar">
224
        <div className="post-bar">
225
          <div className="post_topbar">
226
            <div className="usy-dt">
227
              <img
228
                src={shared_image}
229
                alt=""
230
                style={{
231
                  width: "50px",
232
                  height: "auto",
233
                }}
234
              />
235
              <div className="usy-name">
236
                <h3>{shared_name}</h3>
237
                <span>
238
                  <img
239
                    style={{
240
                      width: "12px",
241
                      height: "auto",
242
                    }}
243
                    src="/images/clock.png"
244
                    alt=""
245
                  />
246
                  {shared_time_elapse}
247
                </span>
248
              </div>
249
            </div>
250
          </div>
251
          <div className="job_descp">
252
            <div className="show-read-more">
253
              {htmlParsedText(shared_description)}
254
            </div>
255
            {shared_file_image ? (
256
              <img src={shared_file_image} className="Entradas" />
257
            ) : null}
258
            {shared_file_video ? (
259
              <video
260
                src={shared_file_video}
261
                controls
262
                poster={shared_file_image_preview}
263
                preload="none"
264
              />
265
            ) : null}
266
            {shared_file_document ? (
267
              <a href={shared_file_document} target="_blank">
268
                Descargar
269
              </a>
270
            ) : null}
271
          </div>
272
        </div>
273
      </div>
274
    );
275
  }
59 steven 276
  const OwnerDescription = () => <div className="show-read-more">
277
    {htmlParsedText(owner_description)}
278
  </div>
55 steven 279
  const TopBar = () => <div className="post_topbar">
280
    <div className="usy-dt">
281
      <a href={owner_url}>
282
        <img
283
          src={owner_image}
284
          alt=""
285
          style={{
286
            width: "50px",
287
            height: "auto",
288
          }}
289
        />
290
      </a>
291
      <div className="usy-name">
292
        <a href={owner_url}>
293
          <h3>{owner_name}</h3>
294
        </a>
295
        <span>
296
          <img src="/images/clock.png" alt="" />
297
          {owner_time_elapse}
298
          {feed_delete_url ? (
299
            <a
300
              href="#"
301
              className="btn-feed-trash"
302
              data-link={feed_delete_url}
303
              data-feed-unique={feed_unique}
304
              onClick={(e) => {
305
                e.preventDefault();
306
                handleShowConfirmModal();
307
              }}
308
            >
309
              <i className="fa fa-trash"></i>
310
            </a>
311
          ) : null}
312
        </span>
313
      </div>
314
    </div>
315
  </div>
1 www 316
 
1021 stevensc 317
  const Content = ({ showDescription }) => <div className="job_descp">
58 steven 318
    {
319
      !!showDescription && (
59 steven 320
        <OwnerDescription />
58 steven 321
      )
322
    }
323
    {owner_file_image ? (
324
      <img src={owner_file_image} className="Entradas" />
325
    ) : null}
326
    {owner_file_video ? (
327
      <video
328
        src={owner_file_video}
329
        controls
330
        poster={owner_file_image_preview}
331
        preload="none"
332
      />
333
    ) : null}
334
    {owner_file_document ? (
335
      <a href={owner_file_document} target="_blank">
336
        Descargar
337
      </a>
338
    ) : null}
339
    {sharedName}
55 steven 340
  </div>
1 www 341
  return (
342
    <React.Fragment>
56 steven 343
      <Modal
344
        show={show}
345
        onHide={handleClose}
59 steven 346
        dialogClassName="modal-md"
56 steven 347
      >
348
        <div
349
          className="row"
350
        >
351
          <div
352
            className="col-md-8 col-sm-12 col-12"
353
          >
205 steven 354
            <Content
355
              showDescription
356
            />
56 steven 357
          </div>
358
          <div
359
            className="col-md-4 col-sm-12 col-12"
360
          >
361
            <TopBar />
59 steven 362
            <OwnerDescription />
56 steven 363
          </div>
364
        </div>
365
      </Modal>
718 steven 366
      <div className={styles.postContainer} >
58 steven 367
        <TopBar
368
          showDescription
369
        />
718 steven 370
        <div
371
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
372
        >
373
          <Content
374
            showDescription
375
          />
376
        </div>
1 www 377
        <div className="job-status-bar">
378
          <ul className="like-com">
379
            <li>
1068 stevensc 380
              {
381
                <button
382
                  id={feedIsLiked ? `btn-unlike-${feed_unique}` : `btn-like-${feed_unique}`}
383
                  data-feed-unique={feed_unique}
384
                  className={feedIsLiked ? "btn-unlike" : "btn-like"}
385
                  onClick={(event) => {
386
                    likeHandler(event, feedIsLiked ? feed_unlike_url : feed_like_url);
387
                  }}
388
                >
389
                  <i className="fas fa-heart"></i>
390
                  {likesState}
391
                </button>
392
              }
393
            </li>
394
            <li>
1 www 395
              <a
396
                href="#"
397
                id={`btn-comments-${feed_unique}`}
398
                className="btn-indicator"
399
              >
722 steven 400
                <i className="fas fa-comments"></i> {totalComments}
1 www 401
              </a>
402
            </li>
403
            <li>
404
              <a
405
                href="#"
406
                id={`btn-share-${feed_unique}`}
407
                className="btn-indicator"
408
              >
1034 stevensc 409
                <i className="fas fa-share"></i> {sharedState}
1 www 410
              </a>
411
            </li>
412
          </ul>
413
          <a
414
            href={feed_share_url}
415
            data-feed-unique={feed_unique}
416
            className="btn-feed-share"
417
            onClick={(e) => {
418
              btnShareHandler(e);
419
            }}
420
          >
421
            <i className="fas fa-share"></i>Compartir
422
          </a>
423
        </div>
424
        {commentsRender}
425
        <div>
426
          <form
427
            className={`form-comment-feed-${feed_unique}`}
428
            data-feed-unique={feed_unique}
429
            onSubmit={handleSubmit(submitCommentHandler)}
430
          >
431
            <div className={styles.feedCommentContainer}>
432
              <input
433
                className={styles.commentInput}
434
                type="text"
435
                name="comment"
436
                id={`comment-${feed_unique}`}
437
                maxLength="256"
438
                placeholder="Escribe un comentario"
439
                ref={register({
440
                  required: {
441
                    value: "true",
442
                    message: "El campo es requerido",
443
                  },
444
                })}
445
              />
446
              <button type="submit" className={styles.submitButton}>
447
                Enviar
448
              </button>{" "}
449
              {/* Falta multilenguaje */}
450
            </div>
451
          </form>
452
          {errors.comment && (
453
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
454
          )}
455
        </div>
456
      </div>
457
      <ConfirmModal
458
        show={showConfirmModal}
459
        onClose={() => {
460
          setShowConfirmModal(false);
461
        }}
462
        onAccept={handleModalAccept}
463
        acceptLabel="Aceptar"
464
      />
465
    </React.Fragment>
466
  );
467
};
468
 
1040 stevensc 469
export default React.memo(FeedTemplate);