Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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