Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 2852 | Rev 3202 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useForm } from "react-hook-form";
import FormErrorFeedback from "../../../shared/form-error-feedback/FormErrorFeedback";
import FeedCommentTemplate from "./feed-comment/FeedCommentTemplate";
import { shareModalTypes } from "../../../redux/share-modal/shareModal.types";
import parse from "html-react-parser";
import { axios } from "../../../utils";
import ConfirmModal from "../../../shared/confirm-modal/ConfirmModal";
import { Modal } from "react-bootstrap";
import { feedTypes } from "../../../redux/feed/feed.types";
import { BsFillTrashFill, BsHeart, BsHeartFill, BsTrash } from 'react-icons/bs'
import { RiShareForwardLine } from 'react-icons/ri'
import { TbSend } from "react-icons/tb";
import { BiDotsVerticalRounded, BiMessage } from "react-icons/bi";
import styles from "./feedTemplate.module.scss";
import styleFeed from "../share-feed/shareFeed.module.scss";

// Redux actions
import { openShareModal } from "../../../redux/share-modal/shareModal.actions";
import { addNotification } from "../../../redux/notification/notification.actions";
import { deleteFeed } from "../../../redux/feed/feed.actions";

const FeedTemplate = ({ feed, owner_shared, image }) => {

  // Destructuring feed data
  const {
    feed_unique,
    owner_name,
    owner_url,
    owner_image,
    owner_time_elapse,
    owner_description,
    owner_file_image,
    owner_file_video,
    owner_file_document,
    owner_file_image_preview,
    shared_name,
    shared_image,
    shared_time_elapse,
    shared_description,
    shared_file_video,
    shared_file_image_preview,
    shared_file_image,
    shared_file_document,
    feed_likes,
    feed_like_url,
    feed_unlike_url,
    feed_is_liked,
    feed_share_url,
    feed_delete_url,
    comments,
    comment_add_url,
  } = feed;

  // react hook form
  const { register, handleSubmit, errors } = useForm();

  const dispatch = useDispatch()

  const [totalComments, setTotalComments] = useState(comments.length || 0);
  const [feedIsLiked, setFeedIsLiked] = useState(feed_is_liked);
  const [commentsState, setCommentsState] = useState(comments);
  const [sharedState, setSharedState] = useState(owner_shared);
  const [likesState, setLikesState] = useState(feed_likes);
  const [isReadMoreActive, setIsReadMoreActive] = useState(false);
  const [showConfirmModal, setShowConfirmModal] = useState(false);
  const [displayOption, setDisplayOption] = useState(false)
  const [show, setShow] = useState(false);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  useEffect(() => {
    setSharedState(owner_shared)
  }, [owner_shared]);

  const deleteFeedHandler = () => {
    axios.post(feed_delete_url)
      .then((res) => {
        const { data } = res
        if (data.success) {
          dispatch(deleteFeed(feed_unique));
          dispatch(addNotification({
            style: "success",
            msg: data.data,
          }));
        } else {
          dispatch(addNotification({
            style: "danger",
            msg: data.data,
          }));
        }
      });
  };

  const handleShowConfirmModal = () => {
    setShowConfirmModal(!showConfirmModal);
  };

  const likeHandler = (likeUrl) => {
    axios.post(likeUrl)
      .then((res) => {
        const { success, data } = res.data;
        if (!success) {
          setFeedIsLiked((previousState) => !previousState);
          dispatch(addNotification({
            style: "danger",
            msg: data,
          }));
        } else {
          setLikesState(data.likes)
          setFeedIsLiked(!feedIsLiked);
        }
      });
  };

  const submitCommentHandler = (data, e) => {
    const currentFormData = new FormData();
    for (let input in data) {
      currentFormData.append(input, data[input]);
    }
    axios.post(comment_add_url, currentFormData).then((res) => {
      const resData = res.data;
      const { data, success, total_comments } = resData;
      if (success) {
        const newComment = data;
        setTotalComments(total_comments);
        setCommentsState([newComment, ...commentsState]);
        e.target.reset();
      } else {
        dispatch(addNotification({
          style: "danger",
          msg: data,
        }));
      }
    });
  };

  const deleteCommentHandler = (commentUnique, deleteCommentUrl) => {
    axios.post(deleteCommentUrl)
      .then((res) => {
        const { success, data, total_comments } = res.data;
        if (success) {
          const newCommentsState = commentsState.filter(
            (comment) => comment.unique !== commentUnique
          );
          setCommentsState(newCommentsState);
          setTotalComments(total_comments);
        } else {
          dispatch(addNotification({
            style: "danger",
            msg: data,
          }));
        }
      })
      .catch((error) => {
        dispatch(addNotification({
          style: "danger",
          msg: error.message,
        }));
      });
  };

  const btnShareHandler = () => {
    dispatch(openShareModal(feed_share_url, shareModalTypes.SHARE, feedTypes.DASHBOARD, feed_unique))
  };

  let commentsRender = null;
  if (commentsState.length) {
    commentsRender = (
      <div className={styles.commentSection}>
        <div className={`comment-sec comment-sec-${feed_unique}`}>
          <ul>
            {[...commentsState].reverse().map((commentData) => {
              const { unique } = commentData;
              return (
                <FeedCommentTemplate
                  commentData={commentData}
                  onDeleteHandler={deleteCommentHandler}
                  key={unique}
                />
              );
            })}
          </ul>
        </div>
      </div>
    );
  }

  const readMoreHandler = (event) => {
    event.preventDefault();
    setIsReadMoreActive(!isReadMoreActive);
  };

  const htmlParsedText = (fullStringText) => {
    const fullText = parse(fullStringText);
    if (fullStringText.length > 500) {
      const shortenedString = fullStringText.substr(0, 500);
      const shortenedText = parse(`${shortenedString}... `);
      return (
        <React.Fragment>
          {isReadMoreActive ? fullText : shortenedText}
          <a
            href="#"
            onClick={(e) => {
              readMoreHandler(e);
            }}
          >
            {isReadMoreActive ? " Leer menos" : " Leer más"}
          </a>
        </React.Fragment>
      );
    } else {
      return fullText;
    }
  };

  let sharedName = null;
  if (shared_name) {
    sharedName = (
      <div className="shared-post-bar">
        <div className="post-bar">
          <div className="post_topbar">
            <div className="usy-dt">
              <img
                src={shared_image}
                alt=""
                style={{
                  width: "50px",
                  height: "auto",
                }}
              />
              <div className="usy-name">
                <h3>{shared_name}</h3>
                <span>
                  {shared_time_elapse}
                </span>
              </div>
            </div>
          </div>
          <div className="job_descp">
            <div className="show-read-more">
              {htmlParsedText(shared_description)}
            </div>
            {shared_file_image ? (
              <img src={shared_file_image} className="Entradas" />
            ) : null}
            {shared_file_video ? (
              <video
                src={shared_file_video}
                controls
                poster={shared_file_image_preview}
                preload="none"
              />
            ) : null}
            {shared_file_document ? (
              <a href={shared_file_document} target="_blank">
                Descargar
              </a>
            ) : null}
          </div>
        </div>
      </div>
    );
  }
  const OwnerDescription = () => <div className="show-read-more">
    {htmlParsedText(owner_description)}
  </div>
  const TopBar = () => (
    < div className="post_topbar" >
      <div className="usy-dt">
        <a href={owner_url}>
          <img src={owner_image} alt="" style={{
            width: "50px",
            height: "auto",
          }}
          />
        </a>
        <div className="usy-name">
          <a href={owner_url}>
            <h3>{owner_name}</h3>
          </a>
          <span>
            {owner_time_elapse}
          </span>
        </div>
      </div>
      {
        feed_delete_url
        &&
        <div className="cursor-pointer d-flex align-items-center">
          <BiDotsVerticalRounded
            onClick={() => setDisplayOption(!displayOption)}
            style={{ fontSize: '1.5rem' }}
          />
          <div className={`feed-options ${displayOption ? 'active' : ''}`}>
            <ul>
              <li>
                <button
                  className="option-btn"
                  onClick={handleShowConfirmModal}
                >
                  <BsTrash className="mr-1" />
                  Delete
                </button>
              </li>
            </ul>
          </div>
        </div>
      }
    </div >
  )

  const Content = ({ showDescription }) => (
    <div className="job_descp">
      {
        showDescription
        &&
        <OwnerDescription />
      }
      {
        owner_file_image
        &&
        <img src={owner_file_image} className="Entradas" />
      }
      {
        owner_file_video
        &&
        <video
          src={owner_file_video}
          controls
          poster={owner_file_image_preview}
          preload="none"
        />
      }
      {
        owner_file_document
        &&
        <a href={owner_file_document} target="_blank">
          Descargar
        </a>
      }
      {sharedName}
    </div>
  )
  return (
    <React.Fragment>
      <Modal
        show={show}
        onHide={handleClose}
        dialogClassName="modal-md"
      >
        <div
          className="row"
        >
          <div
            className="col-md-8 col-sm-12 col-12"
          >
            <Content
              showDescription
            />
          </div>
          <div
            className="col-md-4 col-sm-12 col-12"
          >
            <TopBar />
            <OwnerDescription />
          </div>
        </div>
      </Modal>

      <div className={styles.postContainer}>
        <TopBar
          showDescription
        />
        <div
          onClick={() => (owner_file_image || owner_file_video || owner_file_document) ? handleShow() : null}
        >
          <Content
            showDescription
          />
        </div>
        <div className="job-status-bar">
          <ul className="reactions-list">
            <li>
              <button
                type="button"
                id={feedIsLiked ? `btn-unlike-${feed_unique}` : `btn-like-${feed_unique}`}
                data-feed-unique={feed_unique}
                className={feedIsLiked ? "btn-unlike" : "btn-like"}
                onClick={() => {
                  likeHandler(feedIsLiked ? feed_unlike_url : feed_like_url);
                }}
              >
                {feedIsLiked ? <BsHeartFill className="mr-1" /> : <BsHeart className="mr-1" />}
                {likesState}
              </button>
            </li>
            <li>
              <button
                type="button"
                id={`btn-comments-${feed_unique}`}
                className="btn-indicator"
              >
                <BiMessage className="mr-1" />
                {totalComments}
              </button>
            </li>
            <li>
              <button
                type="button"
                id={`btn-share-${feed_unique}`}
                className="btn-indicator"
                onClick={btnShareHandler}
              >
                <RiShareForwardLine className="mr-1" />
                {sharedState}
              </button>
            </li>
          </ul>
        </div>
        {commentsRender}
        <div>
          <form
            className={`form-comment-feed-${feed_unique}`}
            data-feed-unique={feed_unique}
            onSubmit={handleSubmit(submitCommentHandler)}
          >
            <div className={styles.feedCommentContainer}>
              <img src={image} alt="User profile image" />
              <input
                className={styles.commentInput}
                type="text"
                name="comment"
                id={`comment-${feed_unique}`}
                maxLength="256"
                placeholder="Escribe un comentario"
                ref={register({
                  required: {
                    value: "true",
                    message: "El campo es requerido",
                  },
                })}
              />
              <button className={`${styleFeed.shareIconContainer} ${styleFeed.iconActive}`} >
                <TbSend className={styleFeed.shareIcon} />
              </button>
              {/* Falta multilenguaje */}
            </div>
          </form>
          {
            errors.comment
            &&
            <FormErrorFeedback>{errors.comment.message}</FormErrorFeedback>
          }
        </div>
      </div>
      <ConfirmModal
        show={showConfirmModal}
        onClose={() => setShowConfirmModal(false)}
        onAccept={deleteFeedHandler}
        acceptLabel="Aceptar"
      />
    </React.Fragment>
  );
};

export default React.memo(FeedTemplate);