Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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