Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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