Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 1766 | Autoría | Ultima modificación | Ver Log |

import { useEffect, useState } from 'react'
import { useDispatch } from 'react-redux'

import { axios } from '@app/utils'
import { addNotification } from '@app/redux/notification/notification.actions'
import { showReportModal } from '@app/redux/report/report.actions'

export function useMessages(messagesUrl) {
  const [loading, setLoading] = useState(false)
  const [messages, setMessages] = useState([])
  const [currentPage, setCurrentPage] = useState(1)
  const [pages, setPages] = useState(1)
  const dispatch = useDispatch()

  function compareMessages(ref = [], newValue = []) {
    const set = new Set(ref.map((obj) => obj.id))
    const difference = newValue.filter((obj) => !set.has(obj.id))
    return difference
  }

  const messagesAdapter = (message) => {
    const {
      u,
      side,
      type,
      filename,
      m,
      mtype,
      date,
      time,
      id,
      uuid,
      message: content
    } = message

    return {
      id: id ?? uuid,
      content: m || content || filename || '',
      send: u === 1 || side === 'left',
      contentType: mtype || type,
      time: time || date,
      ...message
    }
  }

  const getMessages = async ({ url = '', page = 1 }) => {
    if (!url) return

    return axios.get(`${url}?page=${page}`).then(({ data: response }) => {
      const { data, success, pagination } = response

      if (!success) {
        throw new Error('Ha ocurrido un error al obtener los mensajes')
      }

      const resMessages = data.items ?? data
      const adapterMessages = resMessages.map((mes) => messagesAdapter(mes))

      return {
        currentPage: pagination ? pagination.current : data.page,
        messages: adapterMessages,
        lastPage: pagination ? pagination.last : data.pages
      }
    })
  }

  const loadMoreMessages = async ({ url = '', page = 2 }) => {
    setLoading(true)
    try {
      const response = await getMessages({ url, page })
      const { messages } = response

      setMessages((prevState) => [...prevState, ...messages])
    } catch (error) {
      dispatch(addNotification({ style: 'danger', msg: error.message }))
    } finally {
      setLoading(false)
    }
  }

  const heartBeat = async ({ url }) => {
    try {
      const { lastPage, messages: resMessages } = await getMessages({ url })

      setPages(lastPage)
      setMessages((prevState) => {
        const diff = compareMessages(prevState, resMessages)
        if (!diff.length) return prevState
        return [...diff, ...prevState]
      })
    } catch (error) {
      dispatch(addNotification({ style: 'danger', msg: error.message }))
    }
  }

  const changePage = () => {
    if (currentPage >= pages) return
    setCurrentPage((prevState) => prevState + 1)
  }

  const markReport = (id) => {
    setMessages((prevMessages) => {
      return prevMessages.map((message) =>
        message.id === id
          ? {
              ...message,
              content: 'Contenido reportado',
              url_abuse_report: '',
              contentType: 'text'
            }
          : message
      )
    })
  }

  const handleReport = ({ url, id }) => {
    dispatch(
      showReportModal({
        reportUrl: url,
        type: 'mensaje',
        onComplete: () => markReport(id)
      })
    )
  }

  useEffect(() => {
    setMessages([])
    setCurrentPage(1)
    setPages(1)
  }, [messagesUrl])

  useEffect(() => {
    if (currentPage === 1) return
    loadMoreMessages({ url: messagesUrl, page: currentPage })
  }, [messagesUrl, currentPage])

  useEffect(() => {
    const messagesInterval = setInterval(() => {
      heartBeat({ url: messagesUrl })
    }, 2000)

    return () => {
      clearInterval(messagesInterval)
    }
  }, [messagesUrl])

  return {
    messages,
    loading,
    loadMore: changePage,
    report: handleReport
  }
}