Rev 5253 | Rev 5603 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
/* eslint-disable react/prop-types */
import React, { useEffect, useRef, useState } from 'react'
import { ArrowLeft } from '@mui/icons-material'
import { useDispatch } from 'react-redux'
import { addNotification } from '../../redux/notification/notification.actions'
import { axios, scrollToBottom } from '../../utils'
import { fetchMessages, getMessagesDifferences } from '../../services/chat'
import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded'
import SpeakerNotesOffRoundedIcon from '@mui/icons-material/SpeakerNotesOffRounded'
import EmptySection from '../../shared/empty-section/EmptySection'
import MessageBox from './MessageBox'
import MessageTemplate from './MessageTemplate'
const DEFAULT_PAGES = { current: 1, last: 1 }
const Chatmail = ({
selectedConversation = null,
setConversation = () => null
}) => {
const [oldMessages, setOldMessages] = useState([])
const [messages, setMessages] = useState([])
const [pages, setPages] = useState(DEFAULT_PAGES)
const [loading, setLoading] = useState(false)
const lastMessage = useRef(null)
const messagesList = useRef(null)
const dispatch = useDispatch()
const getMoreMessages = async (url = '', page = pages.current) => {
try {
setLoading(true)
const response = await fetchMessages(url, page)
if (!response.success) {
const errorMessage = response.data
dispatch(addNotification({ style: 'danger', msg: errorMessage.message }))
return
}
if (response.pagination.current > 1) {
setOldMessages((prevOldMessages) => [...prevOldMessages, ...response.data])
}
setPages((prevPages) => ({ ...prevPages, last: response.pagination.last }))
return
} catch (error) {
const errorMessage = new Error(error)
console.log('Request canceled', errorMessage)
} finally {
setLoading(false)
}
}
const hearBeat = async () => {
try {
setLoading(true)
const response = await fetchMessages(selectedConversation.messages_link, 1)
if (!response.success) {
const errorMessage = response.data
dispatch(addNotification({ style: 'danger', msg: errorMessage.message }))
return
}
const newMessages = getMessagesDifferences(messages, response.data)
if (newMessages.length) {
setMessages([...newMessages, ...messages])
scrollToBottom()
} else {
setMessages(response.data)
}
setPages((prevPages) => ({ ...prevPages, last: response.pagination.last }))
} catch (error) {
const errorMessage = new Error(error)
console.log('Request canceled', errorMessage)
} finally {
setLoading(false)
}
}
const handleSend = async (sendUrl = '', message = {}) => {
try {
const formData = new FormData()
Object.entries(message).forEach(([key, value]) => formData.append(key, value))
const { data: response } = await axios.post(sendUrl, formData)
setMessages(prev => [response.data, ...prev])
} catch (error) {
const errorMessage = new Error(error)
dispatch(addNotification({ style: 'danger', msg: errorMessage.message }))
}
}
const loadMore = async () => {
setPages((prevPages) => ({ ...prevPages, current: prevPages.current + 1 }))
}
useEffect(() => {
if (!loading && selectedConversation) setTimeout(() => hearBeat(), 3000)
}, [loading, selectedConversation])
useEffect(() => {
if (messages) setMessages([])
scrollToBottom(messagesList)
setPages(DEFAULT_PAGES)
}, [selectedConversation])
useEffect(() => {
if (selectedConversation) getMoreMessages(selectedConversation?.messages_link, pages.current)
}, [pages.current])
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
loadMore()
}
})
if (lastMessage.current) {
observer.observe(lastMessage.current)
}
}, [messages])
if (!selectedConversation) {
return <EmptySection message={LABELS.SELECT_CONVERSATION} Icon={<QuestionAnswerRoundedIcon />} />
}
return (
<div className='chat'>
<span className='icon-hide' onClick={() => setConversation(null)}>
<ArrowLeft />
{LABELS.RETURN}
</span>
<a href={selectedConversation.profile}>
<h2 className='chat-header'>{selectedConversation.name}</h2>
</a>
<div className="messages-line" ref={messagesList}>
{messages.length
? [...oldMessages, ...messages].map((element, index) =>
<MessageTemplate
key={index}
message={element}
date={element.date}
/>)
: <EmptySection message={LABELS.NO_MESSAGE_CONVERSATION} Icon={<SpeakerNotesOffRoundedIcon />} />
}
{pages.current < pages.last && <hr ref={lastMessage} style={{ opacity: 0, margin: 0 }} />}
</div>
<MessageBox onSend={handleSend} sendUrl={selectedConversation.send_link} />
</div>
)
}
export default Chatmail