Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

import React, { useEffect, useState } from 'react'
import { axios } from '../../../utils'
import { feedTypes } from '../../../redux/feed/feed.types'
import { deleteFeed } from '../../../redux/feed/feed.actions'
import { openShareModal } from '../../../redux/share-modal/shareModal.actions'
import { shareModalTypes } from '../../../redux/share-modal/shareModal.types'
import { addNotification } from '../../../redux/notification/notification.actions'
import { connect, useDispatch, useSelector } from 'react-redux'
import parse from 'html-react-parser'
import TungstenIcon from '@mui/icons-material/Tungsten'
import FavoriteIcon from '@mui/icons-material/FavoriteTwoTone'
import RecommendIcon from '@mui/icons-material/Recommend'
import AccessTimeIcon from '@mui/icons-material/AccessTime'
import SendOutlinedIcon from '@mui/icons-material/SendOutlined'
import ChatOutlinedIcon from '@mui/icons-material/ChatOutlined'
import ShareOutlinedIcon from '@mui/icons-material/ShareOutlined'
import EmojiEmotionsIcon from '@mui/icons-material/EmojiEmotions'
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism'

import InputOption from './InputOption'
import ConfirmModal from '../../modals/ConfirmModal'
import { CommentForm, CommentsList } from '../CommentSection'
import withExternalShare from './withExternalShare'
import FeedModal from '../FeedModal'
import SurveyForm from '../../survey-form/SurveyForm'

import './Feed.scss'
import ReactionsButton from '../../UI/buttons/ReactionsButton'
import Options from '../../UI/Option'
import { Avatar } from '@mui/material'
import { Link } from 'react-router-dom'

const Feed = (props) => {
  const {
    isShare = false,
    feed_unique,
    feed_share_url,
    feed_share_external_url,
    feed_delete_url,
    feed_my_reaction,
    feed_reactions,
    owner_url,
    image,
    owner_image,
    owner_name,
    owner_description,
    owner_shared,
    owner_comments,
    owner_time_elapse,
    owner_file_image_preview,
    owner_file_video,
    owner_file_image,
    owner_file_document,
    comment_add_url,
    comments: defaultComments,
    shared_name,
    shared_image,
    shared_time_elapse,
    shared_description,
    shared_file_video,
    shared_file_image_preview,
    shared_file_image,
    owner_external_shared,
    shared_file_document,
    shared_url,
    feed_increment_external_counter_url,
    feed_content_type,
    feed_vote_url,
    feed_save_reaction_url,
    feed_delete_reaction_url,
    openShareModal, // REDUX ACTION
  } = props
  const [comments, setComments] = useState([])
  const [ownerReactions, setOwnerReaction] = useState(feed_reactions)
  const [totalComments, setTotalComments] = useState(owner_comments)
  const [externalShare, setExternalShare] = useState(owner_external_shared)
  const [sharedState, setSharedState] = useState(owner_shared)
  const [totalReactions, setTotalReactions] = useState(0)

  const [showComments, setShowComments] = useState(false)
  const [showModal, setShowModal] = useState(false)
  const labels = useSelector(({ intl }) => intl.labels)
  const dispatch = useDispatch()

  const reactionsOptions = [
    {
      type: 'r',
      icon: <RecommendIcon style={{ color: '#7405f9' }} />,
    },
    {
      type: 's',
      icon: <VolunteerActivismIcon style={{ color: '#6495ED' }} />,
    },
    {
      type: 'l',
      icon: <FavoriteIcon style={{ color: '#DF704D' }} />,
    },
    {
      type: 'i',
      icon: (
        <TungstenIcon
          style={{ color: '#F5BB5C', transform: 'rotate(180deg)' }}
        />
      ),
    },
    {
      type: 'f',
      icon: <EmojiEmotionsIcon style={{ color: '#FF7F50' }} />,
    },
  ]

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

  const handleExternalShare = (value) => {
    setExternalShare(value)
  }

  const displayCommentSection = () => {
    setShowComments(!showComments)
  }

  const addComment = ({ comment }) => {
    const formData = new FormData()
    formData.append('comment', comment)

    axios.post(comment_add_url, formData).then((response) => {
      const { success, data, total_comments } = response.data

      if (!success) {
        const errorMessage =
          typeof data === 'string' ? data : 'Error interno. Intente más tarde.'

        dispatch(addNotification({ style: 'danger', msg: errorMessage }))
        return
      }

      setComments((prevMessages) => [...prevMessages, data])
      setTotalComments(total_comments)
    })
  }

  const deleteComment = (commentUnique, deleteCommentUrl) => {
    axios
      .post(deleteCommentUrl)
      .then((response) => {
        const { success, data, total_comments } = response.data

        if (!success) {
          const errorMessage =
            typeof data === 'string'
              ? data
              : 'Error interno. Intente más tarde.'

          dispatch(addNotification({ style: 'danger', msg: errorMessage }))
          return
        }

        dispatch(addNotification({ style: 'success', msg: data }))

        setComments((prevComments) =>
          prevComments.filter((comment) => comment.unique !== commentUnique)
        )
        setTotalComments(total_comments)
      })
      .catch((error) => {
        dispatch(addNotification({ style: 'danger', msg: error }))
        throw new Error(error)
      })
  }

  const ExternalShareButton = withExternalShare(
    InputOption,
    feed_share_external_url,
    {
      Icon: SendOutlinedIcon,
      color: 'gray',
      title: 'Send',
      shareUrl: feed_increment_external_counter_url,
      setValue: handleExternalShare,
      withTitle: true,
    }
  )

  useEffect(() => setSharedState(owner_shared), [owner_shared])

  useEffect(() => {
    const feedReactions = ownerReactions?.reduce(
      (acc, reaction) => acc + Number(reaction.total),
      0
    )
    setTotalReactions(feedReactions)
  }, [ownerReactions])

  useEffect(() => {
    setComments(defaultComments)
  }, [defaultComments])

  return (
    <>
      <div className="feed">
        <Feed.Header
          image={owner_image}
          name={owner_name}
          timeElapsed={owner_time_elapse}
          viewUrl={owner_url}
          deleteUrl={feed_delete_url}
          feedUnique={feed_unique}
        />

        <div
          className="feed__body"
          onClick={() =>
            (owner_file_image || owner_file_video || owner_file_document) &&
            setShowModal(true)
          }
        >
          <Feed.Content
            description={owner_description}
            image={owner_file_image}
            imagePreview={owner_file_image_preview}
            video={owner_file_video}
            document={owner_file_document}
            sharedItem={{
              name: shared_name,
              image: shared_image,
              time_elapse: shared_time_elapse,
              description: shared_description,
              file_video: shared_file_video,
              file_image_preview: shared_file_image_preview,
              file_image: shared_file_image,
              file_document: shared_file_document,
              shared_url,
            }}
            type={feed_content_type}
            voteUrl={feed_vote_url}
          />
        </div>

        {!isShare && feed_content_type !== 'fast-survey' && (
          <div className="px-3 d-flex align-items-center justify-content-between">
            <div className="reactions-counter">
              {reactionsOptions
                .filter((option) =>
                  ownerReactions.find(
                    (reaction) => reaction.reaction === option.type
                  )
                )
                .map((reaction) => reaction.icon)}
              <span>{totalReactions} reacciones</span>
            </div>
            <div
              className="d-inline-flex align-items-center"
              style={{ gap: '5px' }}
            >
              {!!totalComments && (
                <span>{`${totalComments} ${labels.comments?.toLowerCase()}`}</span>
              )}
              {!!sharedState && (
                <span>{`${sharedState} ${labels.shared?.toLowerCase()}`}</span>
              )}
              {!!externalShare && (
                <span>{`${externalShare} ${labels.sends?.toLowerCase()}`}</span>
              )}
            </div>
          </div>
        )}

        {!isShare && feed_content_type !== 'fast-survey' && (
          <div className="feed__buttons">
            <ReactionsButton
              className="feed__share-option position-relative"
              currentReaction={feed_my_reaction}
              saveUrl={feed_save_reaction_url}
              deleteUrl={feed_delete_reaction_url}
              onChange={(reactions) => setOwnerReaction(reactions)}
              withLabel
            />
            <InputOption
              Icon={ChatOutlinedIcon}
              title={labels.comment}
              color="gray"
              onClick={displayCommentSection}
              withTitle
            />
            <InputOption
              Icon={ShareOutlinedIcon}
              title={labels.share}
              color="gray"
              onClick={handleShare}
              withTitle
            />
            <ExternalShareButton />
          </div>
        )}
        {showComments && (
          <div className="px-2 pb-2">
            <CommentForm onSubmit={addComment} image={image} />
            <CommentsList comments={comments} onDelete={deleteComment} />
          </div>
        )}
      </div>
      <FeedModal
        show={showModal}
        feed={props}
        onClose={() => setShowModal(false)}
      />
    </>
  )
}

const Content = ({
  description,
  image,
  imagePreview,
  video,
  document,
  sharedItem,
  type,
  voteUrl,
}) => {
  const [readMore, setReadMore] = useState(false)
  const labels = useSelector(({ intl }) => intl.labels)

  const onReadMore = () => {
    setReadMore(!readMore)
  }

  const htmlParsedText = (fullStringText = '') => {
    const fullText = parse(fullStringText)
    if (fullStringText.length > 500) {
      const shortenedString = fullStringText.substr(0, 500)
      const shortenedText = parse(`${shortenedString}... `)
      return (
        <>
          {readMore ? fullText : shortenedText}
          <span className="cursor-pointer" onClick={onReadMore}>
            {readMore ? labels.read_less : labels.read_more}
          </span>
        </>
      )
    }
    return <p>{fullText}</p>
  }

  return (
    <>
      {type !== 'fast-survey' ? (
        htmlParsedText(description)
      ) : (
        <SurveyForm
          active={description.active}
          question={description.question}
          answers={[
            description.answer1,
            description.answer2,
            description.answer3,
            description.answer4,
            description.answer5,
          ]}
          votes={
            description.votes1 && [
              description.votes1,
              description.votes2,
              description.votes3,
              description.votes4,
              description.votes5,
            ]
          }
          time={description.time_remaining}
          voteUrl={voteUrl}
          resultType={description.result_type}
        />
      )}
      {image && <img src={image} className="Entradas" loading="lazy" />}
      {video && (
        <video src={video} controls poster={imagePreview} preload="none" />
      )}
      {document && (
        <a href={document} target="_blank" rel="noreferrer">
          <img className="pdf" src="/images/extension/pdf.png" alt="pdf" />
        </a>
      )}
      {sharedItem.name && (
        <div className="py-3 px-md-3">
          <Feed
            isShare={true}
            owner_name={sharedItem.name}
            owner_image={sharedItem.image}
            owner_time_elapse={sharedItem.time_elapse}
            owner_description={sharedItem.description}
            owner_file_video={sharedItem.file_video}
            owner_file_image_preview={sharedItem.file_image_preview}
            owner_file_image={sharedItem.file_image}
            owner_file_document={sharedItem.file_document}
            owner_url={sharedItem.shared_url}
          />
        </div>
      )}
    </>
  )
}

const Header = ({
  image = '',
  name = '',
  timeElapsed = '',
  deleteUrl = '',
  viewUrl = '',
  feedUnique = '',
}) => {
  const [showConfirmModal, setShowConfirmModal] = useState(false)
  const [options, setOptions] = useState([])
  const labels = useSelector(({ intl }) => intl.labels)
  const dispatch = useDispatch()

  const toggleConfirm = () => {
    setShowConfirmModal(!showConfirmModal)
  }

  const onDelete = () => {
    axios.post(deleteUrl).then((response) => {
      const { data, success } = response.data

      if (!success) {
        dispatch(addNotification({ style: 'danger', msg: data }))
        return
      }

      dispatch(deleteFeed(feedUnique))
      toggleConfirm()
      dispatch(addNotification({ style: 'success', msg: data }))
    })
  }

  useEffect(() => {
    if (deleteUrl) {
      const deleteOption = { action: toggleConfirm, label: labels.delete }
      setOptions([...options, deleteOption])
    }
  }, [deleteUrl])

  return (
    <div className="feed__header">
      <div className="d-inline-flex">
        <Avatar
          src={image}
          alt={name}
          sx={{ width: '60px', height: '60px', marginRight: '.5rem' }}
        />
        <div className="feed__info">
          <Link to={viewUrl}>
            <h2>{name}</h2>
          </Link>
          <div className="time__elapse">
            <p>{timeElapsed}</p>
            <AccessTimeIcon className="time__elapse-icon" />
          </div>
        </div>
      </div>
      {!!options.length && <Options options={options} />}
      <ConfirmModal
        show={showConfirmModal}
        onClose={toggleConfirm}
        onAccept={onDelete}
      />
    </div>
  )
}

Feed.Content = Content
Feed.Header = Header

const mapDispatchToProps = {
  addNotification: (notification) => addNotification(notification),
  openShareModal: (postUrl, modalType, feedType) =>
    openShareModal(postUrl, modalType, feedType),
}

export default connect(null, mapDispatchToProps)(Feed)