Rev 5198 | Rev 5240 | 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, useLayoutEffect, useRef, useState } from 'react'import EmptySection from '../../shared/empty-section/EmptySection'import MessageBox from './MessageBox'import MessageTemplate from './MessageTemplate'import SpeakerNotesOffRoundedIcon from '@mui/icons-material/SpeakerNotesOffRounded'import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded'import { useDispatch } from 'react-redux'import { fetchMessages, getMessagesDifferences } from '../../services/chat'import { addNotification } from '../../redux/notification/notification.actions'import { axios, scrollToBottom } from '../../utils'import { ArrowLeft } from '@mui/icons-material'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 dispatch = useDispatch()const getMessages = async (url = '', page = DEFAULT_PAGES.current) => {try {setLoading(true)const response = await fetchMessages(url, page)if (!response.success) {const errorMessage = response.datadispatch(addNotification({ style: 'danger', msg: errorMessage.message }))return}const newMessages = getMessagesDifferences(messages, response.data)if (response.pagination.current > 1) {setOldMessages([...response.data, ...oldMessages])}if (newMessages.length) {setMessages([...messages, ...newMessages])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 changeConversation = (conversation) => {setPages(DEFAULT_PAGES)setConversation(conversation)getMessages(selectedConversation.messages_link)}const loadMore = async () => {setPages((prevPages) => ({ ...prevPages, current: prevPages.current + 1 }))}useEffect(() => {let timerif (!loading && selectedConversation) {timer = setTimeout(() => getMessages(selectedConversation.messages_link), 2000)}return () => {clearTimeout(timer)}}, [loading, selectedConversation])useLayoutEffect(() => {getMessages(selectedConversation.messages_link, pages.current)}, [pages.current])useLayoutEffect(() => {const observer = new IntersectionObserver(([entry]) => {if (entry.isIntersecting) {loadMore()}})observer.observe(lastMessage.current)}, [messages])if (!selectedConversation) {return <EmptySection message={LABELS.SELECT_CONVERSATION} Icon={<QuestionAnswerRoundedIcon/>} />}return (<div className='chat'><span className='icon-hide' onClick={() => changeConversation(null)}><ArrowLeft />{LABELS.RETURN}</span><a href={selectedConversation.profile}><h2 className='chat-header'>{selectedConversation.name}</h2></a><div className="messages-line">{messages.length? [...oldMessages, ...messages].map((element, index) =><MessageTemplatekey={index}message={element}date={element.date}/>): <EmptySection message={LABELS.NO_MESSAGE_CONVERSATION} Icon={<SpeakerNotesOffRoundedIcon/>} />}{pages.current < pages.last && <hr ref={lastMessage} style={{ visibility: 'hidden' }} />}</div><MessageBox onSend={handleSend} sendUrl={selectedConversation.send_link}/></div>)}export default Chatmail