Rev 6450 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
/* eslint-disable camelcase */
/* eslint-disable react/prop-types */
import React, { useEffect, useRef, useState } from 'react'
import ChatOutlinedIcon from '@mui/icons-material/ChatOutlined'
import ShareOutlinedIcon from '@mui/icons-material/ShareOutlined'
import SendOutlinedIcon from '@mui/icons-material/SendOutlined'
import InputOption from './InputOption'
import parse from 'html-react-parser'
import Avatar from '../../../../shared/Avatar/Avatar'
import AccessTimeIcon from '@mui/icons-material/AccessTime'
import { axios } from '../../../../utils'
import { addNotification } from '../../../../redux/notification/notification.actions'
import { openShareModal } from '../../../../redux/share-modal/shareModal.actions'
import { shareModalTypes } from '../../../../redux/share-modal/shareModal.types'
import { feedTypes } from '../../../../redux/feed/feed.types'
import FeedCommentSection from '../../../components/feed/feed-comment/FeedCommentSection'
import { connect, useDispatch, useSelector } from 'react-redux'
import withExternalShare from './withExternalShare'
import ConfirmModal from '../../../../shared/confirm-modal/ConfirmModal'
import { deleteFeed } from '../../../../redux/feed/feed.actions'
import FeedModal from '../../../components/feed/FeedModal'
import withReactions from '../../../components/feed/withReaction'
import RecommendIcon from '@mui/icons-material/Recommend'
import FavoriteIcon from '@mui/icons-material/FavoriteTwoTone'
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism'
import EmojiEmotionsIcon from '@mui/icons-material/EmojiEmotions'
import TungstenIcon from '@mui/icons-material/Tungsten'
import SurveyForm from '../../../components/survey-form/SurveyForm'
const Feed = (props) => {
const {
isShare = false,
feed_unique,
feed_share_url,
feed_share_external_url,
feed_delete_url,
feed_my_reaction,
feed_save_reaction_recommended_url,
feed_save_reaction_support_url,
feed_save_reaction_love_url,
feed_save_reaction_interest_url,
feed_save_reaction_fun_url,
feed_delete_reaction_url,
feed_reactions,
owner_url,
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,
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,
addNotification, // REDUX ACTION
openShareModal, // REDUX ACTION
} = props
const [ownerReactions, setOwnerReaction] = useState(feed_reactions)
const [currentReaction, setCurrentReaction] = useState(feed_my_reaction)
const [totalReactions, setTotalReactions] = useState(0)
const [totalComments, setTotalComments] = useState(owner_comments)
const [externalShare, setExternalShare] = useState(owner_external_shared)
const [sharedState, setSharedState] = useState(owner_shared)
const [showComments, setShowComments] = useState(false)
const [showModal, setShowModal] = useState(false)
const labels = useSelector(({ labels }) => labels)
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 saveReaction = async (type) => {
const reactionTypesUrl = {
r: feed_save_reaction_recommended_url,
s: feed_save_reaction_support_url,
l: feed_save_reaction_love_url,
i: feed_save_reaction_interest_url,
f: feed_save_reaction_fun_url,
}
await axios.post(reactionTypesUrl[type]).then((res) => {
const { success, data } = res.data
if (!success) {
addNotification({ style: 'danger', msg: data })
}
setOwnerReaction(data.reactions)
setCurrentReaction(type)
})
}
const deleteReaction = async () => {
await axios.post(feed_delete_reaction_url).then((res) => {
const { success, data } = res.data
if (!success) {
addNotification({ style: 'danger', msg: data })
return
}
setOwnerReaction(data.reactions)
setCurrentReaction('')
})
}
const ExternalShareButton = withExternalShare(
InputOption,
feed_share_external_url,
{
Icon: SendOutlinedIcon,
color: 'gray',
title: 'Send',
shareUrl: feed_increment_external_counter_url,
setValue: handleExternalShare,
withTitle: true,
}
)
const WithReactionIcon = withReactions(InputOption, {
onSelect: saveReaction,
onDelete: deleteReaction,
myReaction: currentReaction,
withTitle: true,
})
useEffect(() => setSharedState(owner_shared), [owner_shared])
useEffect(() => {
const feedReactions = ownerReactions?.reduce(
(acc, reaction) => acc + Number(reaction.total),
0
)
setTotalReactions(feedReactions)
}, [ownerReactions])
return (
<>
{showModal && (
<FeedModal
isShow={true}
feed={props}
handleClose={() => setShowModal(false)}
/>
)}
<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">
<WithReactionIcon withTitle />
<InputOption
Icon={ChatOutlinedIcon}
title={labels.COMMENT}
color="gray"
onClick={displayCommentSection}
withTitle
/>
<InputOption
Icon={ShareOutlinedIcon}
title={labels.SHARE}
color="gray"
onClick={handleShare}
withTitle
/>
<ExternalShareButton />
</div>
)}
<div className="px-2 pb-2">
<FeedCommentSection
feedId={feed_unique}
image={owner_image}
addUrl={comment_add_url}
updateTotalComments={(total) => setTotalComments(total)}
currentComments={comments}
isShow={showComments}
/>
</div>
</div>
</>
)
}
const Content = ({
description,
image,
imagePreview,
video,
document,
sharedItem,
type,
voteUrl,
}) => {
const [isReadMoreActive, setIsReadMoreActive] = useState(false)
const labels = useSelector(({ labels }) => labels)
const readMoreHandler = () => setIsReadMoreActive(!isReadMoreActive)
const htmlParsedText = (fullStringText) => {
const fullText = parse(fullStringText)
if (fullStringText.length > 500) {
const shortenedString = fullStringText.substr(0, 500)
const shortenedText = parse(`${shortenedString}... `)
return (
<>
{isReadMoreActive ? fullText : shortenedText}
<span className="cursor-pointer" onClick={readMoreHandler}>
{isReadMoreActive ? 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">
{labels.DOWNLOAD}
</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 [displayOption, setDisplayOption] = useState(false)
const deleteButton = useRef()
const dispatch = useDispatch()
const labels = useSelector(({ labels }) => labels)
const handleShowConfirmModal = () => setShowConfirmModal(!showConfirmModal)
const deleteFeedHandler = () => {
axios.post(deleteUrl).then((res) => {
const { data } = res
if (!data.success) {
dispatch(addNotification({ style: 'danger', msg: data.data }))
return
}
dispatch(addNotification({ style: 'success', msg: data.data }))
handleShowConfirmModal()
dispatch(deleteFeed(feedUnique))
})
}
useEffect(() => {
const handleClickOutside = (event) => {
if (
deleteButton.current &&
!deleteButton.current.contains(event.target)
) {
setDisplayOption(false)
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [deleteButton])
return (
<div className="feed__header">
<div className="d-inline-flex" style={{ gap: '.5rem' }}>
<Avatar imageUrl={image} name={name} size="xl" />
<div className="feed__info">
<a href={viewUrl}>
<h2>{name}</h2>
</a>
<div className="time__elapse">
<p>{timeElapsed}</p>
<AccessTimeIcon className="time__elapse-icon" />
</div>
</div>
</div>
{deleteUrl && (
<div className="cursor-pointer d-flex align-items-center position-relative">
<img
src="/images/icons/options.png"
className="cursor-pointer img-icon options"
onClick={() => setDisplayOption(!displayOption)}
/>
<div className={`feed-options ${displayOption ? 'active' : ''}`}>
<ul>
<li>
<button
className="option-btn"
onClick={handleShowConfirmModal}
ref={deleteButton}
>
<i className="fa fa-trash-o mr-1" />
{labels.DELETE}
</button>
</li>
</ul>
</div>
<ConfirmModal
show={showConfirmModal}
onClose={() => handleShowConfirmModal(false)}
onAccept={deleteFeedHandler}
acceptLabel={labels.ACCEPT}
/>
</div>
)}
</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)