Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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