Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 2215 | Rev 2570 | 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";
2240 stevensc 13
import { BsFillChatDotsFill, BsFillTrashFill, BsHeart, BsHeartFill } from 'react-icons/bs'
14
import { FaShare } from 'react-icons/fa'
1 www 15
 
1034 stevensc 16
// Redux actions
17
import { openShareModal } from "../../../redux/share-modal/shareModal.actions";
18
import { addNotification } from "../../../redux/notification/notification.actions";
19
import { deleteFeed } from "../../../redux/feed/feed.actions";
20
 
1048 stevensc 21
const FeedTemplate = ({ feed, owner_shared }) => {
1034 stevensc 22
 
1 www 23
  // Destructuring feed data
24
  const {
25
    feed_unique,
26
    owner_name,
27
    owner_url,
28
    owner_image,
29
    owner_comments,
30
    owner_time_elapse,
31
    owner_description,
32
    owner_file_image,
33
    owner_file_video,
34
    owner_file_document,
35
    owner_file_image_preview,
36
    shared_name,
37
    shared_image,
38
    shared_time_elapse,
39
    shared_description,
40
    shared_file_video,
41
    shared_file_image_preview,
42
    shared_file_image,
43
    shared_file_document,
44
    feed_like_url,
45
    feed_unlike_url,
46
    feed_is_liked,
1048 stevensc 47
    feed_likes,
1 www 48
    feed_share_url,
49
    feed_delete_url,
50
    comments,
51
    comment_add_url,
1040 stevensc 52
  } = feed;
1 www 53
 
1034 stevensc 54
  // react hook form
55
  const { register, handleSubmit, errors } = useForm();
722 steven 56
 
1034 stevensc 57
  const dispatch = useDispatch()
1 www 58
 
1291 stevensc 59
  const [totalComments, setTotalComments] = useState(comments.length || 0);
1 www 60
  const [feedIsLiked, setFeedIsLiked] = useState(feed_is_liked);
61
  const [commentsState, setCommentsState] = useState(comments);
1034 stevensc 62
  const [sharedState, setSharedState] = useState(owner_shared);
1047 stevensc 63
  const [likesState, setLikesState] = useState(feed_likes);
1 www 64
  const [isReadMoreActive, setIsReadMoreActive] = useState(false);
65
  const [showConfirmModal, setShowConfirmModal] = useState(false);
56 steven 66
  const [show, setShow] = useState(false);
1 www 67
 
1034 stevensc 68
  const handleClose = () => setShow(false);
69
  const handleShow = () => setShow(true);
70
 
71
  useEffect(() => {
72
    setSharedState(owner_shared)
1032 stevensc 73
  }, [owner_shared]);
1030 stevensc 74
 
1 www 75
  const deleteFeedHandler = () => {
1043 stevensc 76
    axios.post(feed_delete_url)
1046 stevensc 77
      .then((res) => {
78
        const { data } = res
1043 stevensc 79
        if (data.success) {
80
          dispatch(deleteFeed(feed_unique));
81
          dispatch(addNotification({
82
            style: "success",
83
            msg: data.data,
84
          }));
85
        } else {
86
          dispatch(addNotification({
87
            style: "danger",
88
            msg: data.data,
89
          }));
90
        }
91
      });
1 www 92
  };
93
 
94
  const handleShowConfirmModal = () => {
95
    setShowConfirmModal(!showConfirmModal);
96
  };
97
 
1072 stevensc 98
  const likeHandler = (likeUrl) => {
1043 stevensc 99
    axios.post(likeUrl)
1046 stevensc 100
      .then((res) => {
101
        const { success, data } = res.data;
1043 stevensc 102
        if (!success) {
103
          setFeedIsLiked((previousState) => !previousState);
104
          dispatch(addNotification({
105
            style: "danger",
106
            msg: data,
107
          }));
1049 stevensc 108
        } else {
109
          setLikesState(data.likes)
110
          setFeedIsLiked(!feedIsLiked);
1043 stevensc 111
        }
112
      });
1 www 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);
1084 stevensc 126
        setCommentsState([newComment, ...commentsState]);
1 www 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) => {
1068 stevensc 138
    axios.post(deleteCommentUrl)
1 www 139
      .then((res) => {
975 steven 140
        const { success, data, total_comments } = res.data;
1 www 141
        if (success) {
142
          const newCommentsState = commentsState.filter(
143
            (comment) => comment.unique !== commentUnique
144
          );
145
          setCommentsState(newCommentsState);
975 steven 146
          setTotalComments(total_comments);
1 www 147
        } else {
1034 stevensc 148
          dispatch(addNotification({
1 www 149
            style: "danger",
150
            msg: data,
1034 stevensc 151
          }));
1 www 152
        }
153
      })
154
      .catch((error) => {
1034 stevensc 155
        dispatch(addNotification({
1 www 156
          style: "danger",
157
          msg: error.message,
1034 stevensc 158
        }));
1 www 159
      });
160
  };
161
 
1084 stevensc 162
  const btnShareHandler = () => {
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
  const readMoreHandler = (event) => {
189
    event.preventDefault();
190
    setIsReadMoreActive(!isReadMoreActive);
191
  };
192
 
193
  const htmlParsedText = (fullStringText) => {
194
    const fullText = parse(fullStringText);
195
    if (fullStringText.length > 500) {
196
      const shortenedString = fullStringText.substr(0, 500);
197
      const shortenedText = parse(`${shortenedString}... `);
198
      return (
199
        <React.Fragment>
200
          {isReadMoreActive ? fullText : shortenedText}
201
          <a
202
            href="#"
203
            onClick={(e) => {
204
              readMoreHandler(e);
205
            }}
206
          >
207
            {isReadMoreActive ? " Leer menos" : " Leer más"}
208
          </a>
209
        </React.Fragment>
210
      );
211
    } else {
212
      return fullText;
213
    }
214
  };
215
 
216
  let sharedName = null;
217
  if (shared_name) {
218
    sharedName = (
219
      <div className="shared-post-bar">
220
        <div className="post-bar">
221
          <div className="post_topbar">
222
            <div className="usy-dt">
223
              <img
224
                src={shared_image}
225
                alt=""
226
                style={{
227
                  width: "50px",
228
                  height: "auto",
229
                }}
230
              />
231
              <div className="usy-name">
232
                <h3>{shared_name}</h3>
233
                <span>
234
                  {shared_time_elapse}
235
                </span>
236
              </div>
237
            </div>
238
          </div>
239
          <div className="job_descp">
240
            <div className="show-read-more">
241
              {htmlParsedText(shared_description)}
242
            </div>
243
            {shared_file_image ? (
244
              <img src={shared_file_image} className="Entradas" />
245
            ) : null}
246
            {shared_file_video ? (
247
              <video
248
                src={shared_file_video}
249
                controls
250
                poster={shared_file_image_preview}
251
                preload="none"
252
              />
253
            ) : null}
254
            {shared_file_document ? (
255
              <a href={shared_file_document} target="_blank">
256
                Descargar
257
              </a>
258
            ) : null}
259
          </div>
260
        </div>
261
      </div>
262
    );
263
  }
59 steven 264
  const OwnerDescription = () => <div className="show-read-more">
265
    {htmlParsedText(owner_description)}
266
  </div>
1084 stevensc 267
  const TopBar = () => (
268
    <div className="post_topbar">
269
      <div className="usy-dt">
270
        <a href={owner_url}>
271
          <img src={owner_image} alt="" style={{
55 steven 272
            width: "50px",
273
            height: "auto",
274
          }}
1084 stevensc 275
          />
55 steven 276
        </a>
1084 stevensc 277
        <div className="usy-name">
278
          <a href={owner_url}>
279
            <h3>{owner_name}</h3>
280
          </a>
281
          <span>
282
            {owner_time_elapse}
283
          </span>
284
        </div>
55 steven 285
      </div>
1084 stevensc 286
    </div >
287
  )
1 www 288
 
1079 stevensc 289
  const Content = ({ showDescription }) => (
290
    <div className="job_descp">
291
      {
292
        showDescription
293
        &&
59 steven 294
        <OwnerDescription />
1079 stevensc 295
      }
296
      {
297
        owner_file_image
298
        &&
299
        <img src={owner_file_image} className="Entradas" />
300
      }
301
      {
302
        owner_file_video
303
        &&
304
        <video
305
          src={owner_file_video}
306
          controls
307
          poster={owner_file_image_preview}
308
          preload="none"
309
        />
310
      }
311
      {
312
        owner_file_document
313
        &&
314
        <a href={owner_file_document} target="_blank">
315
          Descargar
316
        </a>
317
      }
318
      {sharedName}
319
    </div>
320
  )
1 www 321
  return (
322
    <React.Fragment>
56 steven 323
      <Modal
324
        show={show}
325
        onHide={handleClose}
59 steven 326
        dialogClassName="modal-md"
56 steven 327
      >
328
        <div
329
          className="row"
330
        >
331
          <div
332
            className="col-md-8 col-sm-12 col-12"
333
          >
205 steven 334
            <Content
335
              showDescription
336
            />
56 steven 337
          </div>
338
          <div
339
            className="col-md-4 col-sm-12 col-12"
340
          >
341
            <TopBar />
59 steven 342
            <OwnerDescription />
56 steven 343
          </div>
344
        </div>
345
      </Modal>
1084 stevensc 346
 
347
      <div className={styles.postContainer}>
58 steven 348
        <TopBar
349
          showDescription
350
        />
718 steven 351
        <div
352
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
353
        >
354
          <Content
355
            showDescription
356
          />
357
        </div>
1 www 358
        <div className="job-status-bar">
359
          <ul className="like-com">
360
            <li>
1082 stevensc 361
              <button
362
                type="button"
363
                id={feedIsLiked ? `btn-unlike-${feed_unique}` : `btn-like-${feed_unique}`}
364
                data-feed-unique={feed_unique}
365
                className={feedIsLiked ? "btn-unlike" : "btn-like"}
366
                onClick={() => {
367
                  likeHandler(feedIsLiked ? feed_unlike_url : feed_like_url);
368
                }}
369
              >
2240 stevensc 370
                {feedIsLiked ? <BsHeartFill /> : <BsHeart />}
1082 stevensc 371
              </button>
1068 stevensc 372
            </li>
373
            <li>
1080 stevensc 374
              <button
375
                type="button"
1 www 376
                id={`btn-comments-${feed_unique}`}
377
                className="btn-indicator"
378
              >
2240 stevensc 379
                <BsFillChatDotsFill />
1080 stevensc 380
              </button>
1 www 381
            </li>
382
            <li>
1080 stevensc 383
              <button
384
                type="button"
1 www 385
                id={`btn-share-${feed_unique}`}
386
                className="btn-indicator"
2211 stevensc 387
                onClick={btnShareHandler}
388
              >
2240 stevensc 389
                <FaShare />
2211 stevensc 390
              </button>
391
            </li>
2212 stevensc 392
            {
393
              feed_delete_url
394
              &&
395
              <li>
396
                <button
397
                  type="button"
398
                  className="btn-feed-share"
399
                  data-link={feed_delete_url}
400
                  data-feed-unique={feed_unique}
401
                  onClick={handleShowConfirmModal}
402
                >
2240 stevensc 403
                  <BsFillTrashFill />
2212 stevensc 404
                </button>
405
              </li>
406
            }
1 www 407
          </ul>
408
        </div>
409
        {commentsRender}
410
        <div>
411
          <form
412
            className={`form-comment-feed-${feed_unique}`}
413
            data-feed-unique={feed_unique}
414
            onSubmit={handleSubmit(submitCommentHandler)}
415
          >
416
            <div className={styles.feedCommentContainer}>
417
              <input
418
                className={styles.commentInput}
419
                type="text"
420
                name="comment"
421
                id={`comment-${feed_unique}`}
422
                maxLength="256"
423
                placeholder="Escribe un comentario"
424
                ref={register({
425
                  required: {
426
                    value: "true",
427
                    message: "El campo es requerido",
428
                  },
429
                })}
430
              />
2215 stevensc 431
              <button type="submit" className="btn btn-primary" style={{ padding: '2px 10px' }}>
1483 steven 432
                Comentar
1084 stevensc 433
              </button>
1 www 434
              {/* Falta multilenguaje */}
435
            </div>
436
          </form>
1084 stevensc 437
          {
438
            errors.comment
439
            &&
1 www 440
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
1084 stevensc 441
          }
1 www 442
        </div>
443
      </div>
1084 stevensc 444
 
1 www 445
      <ConfirmModal
446
        show={showConfirmModal}
1084 stevensc 447
        onClose={() => setShowConfirmModal(false)}
448
        onAccept={deleteFeedHandler}
1 www 449
        acceptLabel="Aceptar"
450
      />
451
    </React.Fragment>
452
  );
453
};
454
 
1040 stevensc 455
export default React.memo(FeedTemplate);