Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 15765 | Rev 16782 | 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, useState } from "react";
import { axios } from "../../utils";
import { FiMaximize2 } from "react-icons/fi";
import AddIcon from "@mui/icons-material/Add";

// Components
import NotificationAlert from "../../shared/notification/NotificationAlert";
import PersonalChat from "./personal-chat/PersonalChat";
import ContactsModal from "./components/ContactsModal";
import ContactsFilters from "./components/contactsFilters";

const notifyAudio = new Audio("/audio/chat.mp3");

const Chat = ({ emojiOnePath, timezones }) => {
  const [contacts, setContacts] = useState([]);
  const [activeChats, setActiveChats] = useState([]);
  const [isChatOpen, setIsChatOpen] = useState(false);
  const [isMuted, setIsMuted] = useState(false);
  const [showModal, setShowModal] = useState(false);
  const [loading, setLoading] = useState(false);

  const [pendingConversation, setPendingConversation] = useState("");

  const handleEntities = (entities) => {
    entities.map((entity) => {
      if (entity.not_received_messages) handleNewMessage(entity);
      if (entity.not_seen_messages) handleNotSeenMessage(entity);
      if (entity.is_open) handleOpenConversation(entity, false);
      if (entity.type === "user") handleUpdateOnline(entity);
    });
    setContacts(entities);
  };

  const heartBeat = async () => {
    try {
      setLoading(true);
      const { data } = await axios.get("/chat/heart-beat");
      if (data.success) handleEntities(data.data);
      setLoading(false);
      return data.data;
    } catch (error) {
      console.log(">>: chat error > ", error);
    }
  };

  const handleUpdateOnline = (entity) => {
    const existingChatId = activeChats.findIndex(
      (activeChat) => activeChat.id === entity.id
    );
    if (existingChatId >= 0) {
      if (activeChats[existingChatId].online !== entity.online) {
        const newActiveChats = [...activeChats];
        newActiveChats[existingChatId].online = entity.online;
        setActiveChats(newActiveChats);
      }
    }
  };

  const handleNewMessage = async (unseeEntity) => {
    await axios.post(unseeEntity.url_mark_received);
    if (!activeChats.some((activeChat) => activeChat.id === unseeEntity.id)) {
      setActiveChats([...activeChats, { ...unseeEntity, minimized: false }]);
      playNotifyAudio();
    } else {
      const existingChatId = activeChats.findIndex(
        (activeChat) => activeChat.id === unseeEntity.id
      );
      if (!activeChats[existingChatId].unsee_messages) {
        const newActiveChats = [...activeChats];
        newActiveChats[existingChatId].unsee_messages = true;
        setActiveChats(newActiveChats);
        playNotifyAudio(newActiveChats[existingChatId].minimized);
      }
    }
  };

  const handleCloseConversation = async (entity) => {
    const { data } = await axios.post(entity.url_close);
    if (!data.success) console.log("Error in entity close");
    setActiveChats(
      activeChats.filter((prevActiveChats) => prevActiveChats.id !== entity.id)
    );
  };

  const handleOpenConversation = async (entity, minimized = false) => {
    if (activeChats.some((el) => el.id === entity.id)) {
      return null;
    }

    if (activeChats.length >= 3) {
      await handleCloseConversation(activeChats[0]);
      setActiveChats((prevActiveChats) => [
        ...prevActiveChats,
        { ...entity, minimized },
      ]);
      return;
    }

    setActiveChats((prevActiveChats) => [
      ...prevActiveChats,
      { ...entity, minimized },
    ]);
  };

  const handleReadConversation = async (entity) => {
    try {
      const { data } = await axios.post(entity.url_mark_seen);
      if (!data.success) console.log("Ha ocurrido un error");
      setActiveChats((prevActiveChats) =>
        [...prevActiveChats].map((chat) => {
          if (entity.id === chat.id)
            return { ...chat, not_seen_messages: false };
          return chat;
        })
      );
    } catch (error) {
      console.log(`Error: ${error}`);
    }
  };

  const handleMinimizeConversation = (entity, minimized = null) => {
    return setActiveChats((prevActiveChats) =>
      [...prevActiveChats].map((chat) => {
        if (entity.id === chat.id)
          return { ...chat, minimized: minimized ?? !chat.minimized };
        return chat;
      })
    );
  };

  const handleNotSeenMessage = (entity) => {
    const index = activeChats.findIndex((chat) => chat.id === entity.id);

    if (index !== -1) {
      setActiveChats((prev) =>
        [...prev].map((chat) => {
          if (chat.id === entity.id) {
            return {
              ...chat,
              not_seen_messages: entity.not_seen_messages,
            };
          }
          return chat;
        })
      );
    }
  };

  const playNotifyAudio = (minimized = true) => {
    if (!isMuted && minimized) {
      notifyAudio.play();
    }
  };

  const handleMute = () => {
    setIsMuted(!isMuted);
    if (isMuted) {
      notifyAudio.play();
    }
  };

  useEffect(() => {
    if (!loading) setTimeout(() => heartBeat(), 2000);
  }, [loading]);

  useEffect(() => {
    if (pendingConversation) {
      const pendingChat = contacts.find(
        (contact) => contact.url_send === pendingConversation
      );

      if (pendingChat) {
        handleOpenConversation(pendingChat);
        setPendingConversation("");
      }
    }
  }, [pendingConversation, contacts]);

  useEffect(() => {
    emojione.imageType = "png";
    emojione.sprites = false;
    emojione.ascii = true;
    emojione.imagePathPNG = emojiOnePath;
  }, []);

  if (window.innerWidth < 1000 || window.location.pathname === "/chat")
    return null;

  return (
    <>
      <div className="chat-helper">
        <div
          className="subpanel_title"
          onClick={(e) =>
            e.currentTarget === e.target && setIsChatOpen(!isChatOpen)
          }
        >
          <a href="/chat" className="text-chat-title">
            {CHAT_LABELS.CHAT}
            <FiMaximize2 className="ml-3" />
          </a>

          <div className="subpanel_title-icons">
            <i
              className={`icon ${
                isMuted ? "icon-volume-off" : "icon-volume-2"
              } text-20`}
              onClick={handleMute}
            />
            <i
              className={`fa ${
                isChatOpen ? "fa-angle-down" : "fa-angle-up"
              } text-20`}
              onClick={() => setIsChatOpen(!isChatOpen)}
            />
          </div>
        </div>
        {isChatOpen && (
          <>
            <button className="action-btn" onClick={() => setShowModal(true)}>
              <AddIcon />
              {CHAT_LABELS.START_CONVERSATION}
            </button>
            <ContactsFilters
              dataset={contacts}
              selectConversation={(entity) => handleOpenConversation(entity)}
            />
          </>
        )}
      </div>

      <div className="active_chats-list">
        {activeChats.map((entity, index) => (
          <PersonalChat
            index={index}
            key={entity.id}
            entity={entity}
            not_seen_messages={entity.not_seen_messages}
            minimized={entity.minimized}
            onClose={handleCloseConversation}
            onMinimize={handleMinimizeConversation}
            onRead={handleReadConversation}
            timezones={timezones}
          />
        ))}
      </div>
      <ContactsModal show={showModal} onClose={() => setShowModal(false)} />
      <NotificationAlert />
    </>
  );
};

export default Chat;