Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3208 | Ir a la última revisión | Autoría | Comparar con el anterior | 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;
    setLoading(true);
    return axios
      .get(`${url}?page=${page}`)
      .then((response) => {
        const { data, success, pagination } = response.data;

        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,
        };
      })
      .finally(() => setLoading(false));
  };

  const loadMoreMessages = async ({ url = "", page = 2 }) => {
    try {
      const response = await getMessages({ url, page });
      const { messages } = response;

      setMessages((prevState) => [...prevState, ...messages]);
    } catch (error) {
      dispatch(addNotification({ style: "danger", msg: error.message }));
    }
  };

  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, loading]);

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

    return () => {
      clearTimeout(messagesInterval);
    };
  }, [messagesUrl, loading]);

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