Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 15761 | Rev 15766 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
15761 stevensc 1
/* eslint-disable react/prop-types */
15765 stevensc 2
import React, { useEffect, useState } from "react";
3
import { axios } from "../../utils";
4
import { FiMaximize2 } from "react-icons/fi";
5
import AddIcon from "@mui/icons-material/Add";
15761 stevensc 6
 
7
// Components
15765 stevensc 8
import NotificationAlert from "../../shared/notification/NotificationAlert";
9
import PersonalChat from "./personal-chat/PersonalChat";
10
import ContactsModal from "./components/ContactsModal";
11
import ContactsFilters from "./components/contactsFilters";
15761 stevensc 12
 
15765 stevensc 13
const notifyAudio = new Audio("/audio/chat.mp3");
15761 stevensc 14
 
15765 stevensc 15
const Chat = ({ emojiOnePath, timezones = {} }) => {
16
  const [contacts, setContacts] = useState([]);
17
  const [activeChats, setActiveChats] = useState([]);
18
  const [isChatOpen, setIsChatOpen] = useState(false);
19
  const [isMuted, setIsMuted] = useState(false);
20
  const [showModal, setShowModal] = useState(false);
21
  const [loading, setLoading] = useState(false);
15761 stevensc 22
 
15765 stevensc 23
  const [pendingConversation, setPendingConversation] = useState("");
15761 stevensc 24
 
25
  const handleEntities = (entities) => {
26
    entities.map((entity) => {
15765 stevensc 27
      if (entity.not_received_messages) handleNewMessage(entity);
28
      if (entity.not_seen_messages) handleNotSeenMessage(entity);
29
      if (entity.is_open) handleOpenConversation(entity, false);
30
      if (entity.type === "user") handleUpdateOnline(entity);
31
    });
32
    setContacts(entities);
33
  };
15761 stevensc 34
 
35
  const heartBeat = async () => {
36
    try {
15765 stevensc 37
      setLoading(true);
38
      const { data } = await axios.get("/chat/heart-beat");
39
      if (data.success) handleEntities(data.data);
40
      setLoading(false);
41
      return data.data;
15761 stevensc 42
    } catch (error) {
15765 stevensc 43
      console.log(">>: chat error > ", error);
15761 stevensc 44
    }
15765 stevensc 45
  };
15761 stevensc 46
 
47
  const handleUpdateOnline = (entity) => {
48
    const existingChatId = activeChats.findIndex(
49
      (activeChat) => activeChat.id === entity.id
15765 stevensc 50
    );
15761 stevensc 51
    if (existingChatId >= 0) {
52
      if (activeChats[existingChatId].online !== entity.online) {
15765 stevensc 53
        const newActiveChats = [...activeChats];
54
        newActiveChats[existingChatId].online = entity.online;
55
        setActiveChats(newActiveChats);
15761 stevensc 56
      }
57
    }
15765 stevensc 58
  };
15761 stevensc 59
 
60
  const handleNewMessage = async (unseeEntity) => {
15765 stevensc 61
    await axios.post(unseeEntity.url_mark_received);
15761 stevensc 62
    if (!activeChats.some((activeChat) => activeChat.id === unseeEntity.id)) {
15765 stevensc 63
      setActiveChats([...activeChats, { ...unseeEntity, minimized: false }]);
64
      playNotifyAudio();
15761 stevensc 65
    } else {
66
      const existingChatId = activeChats.findIndex(
67
        (activeChat) => activeChat.id === unseeEntity.id
15765 stevensc 68
      );
15761 stevensc 69
      if (!activeChats[existingChatId].unsee_messages) {
15765 stevensc 70
        const newActiveChats = [...activeChats];
71
        newActiveChats[existingChatId].unsee_messages = true;
72
        setActiveChats(newActiveChats);
73
        playNotifyAudio(newActiveChats[existingChatId].minimized);
15761 stevensc 74
      }
75
    }
15765 stevensc 76
  };
15761 stevensc 77
 
78
  const handleCloseConversation = async (entity) => {
15765 stevensc 79
    const { data } = await axios.post(entity.url_close);
80
    if (!data.success) console.log("Error in entity close");
15761 stevensc 81
    setActiveChats(
82
      activeChats.filter((prevActiveChats) => prevActiveChats.id !== entity.id)
15765 stevensc 83
    );
84
  };
15761 stevensc 85
 
86
  const handleOpenConversation = async (entity, minimized = false) => {
87
    if (activeChats.some((el) => el.id === entity.id)) {
15765 stevensc 88
      return null;
15761 stevensc 89
    }
90
 
91
    if (activeChats.length >= 3) {
15765 stevensc 92
      await handleCloseConversation(activeChats[0]);
15761 stevensc 93
      setActiveChats((prevActiveChats) => [
94
        ...prevActiveChats,
95
        { ...entity, minimized },
15765 stevensc 96
      ]);
97
      return;
15761 stevensc 98
    }
99
 
100
    setActiveChats((prevActiveChats) => [
101
      ...prevActiveChats,
102
      { ...entity, minimized },
15765 stevensc 103
    ]);
104
  };
15761 stevensc 105
 
106
  const handleReadConversation = async (entity) => {
107
    try {
15765 stevensc 108
      const { data } = await axios.post(entity.url_mark_seen);
109
      if (!data.success) console.log("Ha ocurrido un error");
15761 stevensc 110
      setActiveChats((prevActiveChats) =>
111
        [...prevActiveChats].map((chat) => {
112
          if (entity.id === chat.id)
15765 stevensc 113
            return { ...chat, not_seen_messages: false };
114
          return chat;
15761 stevensc 115
        })
15765 stevensc 116
      );
15761 stevensc 117
    } catch (error) {
15765 stevensc 118
      console.log(`Error: ${error}`);
15761 stevensc 119
    }
15765 stevensc 120
  };
15761 stevensc 121
 
122
  const handleMinimizeConversation = (entity, minimized = null) => {
123
    return setActiveChats((prevActiveChats) =>
124
      [...prevActiveChats].map((chat) => {
125
        if (entity.id === chat.id)
15765 stevensc 126
          return { ...chat, minimized: minimized ?? !chat.minimized };
127
        return chat;
15761 stevensc 128
      })
15765 stevensc 129
    );
130
  };
15761 stevensc 131
 
132
  const handleNotSeenMessage = (entity) => {
15765 stevensc 133
    const index = activeChats.findIndex((chat) => chat.id === entity.id);
15761 stevensc 134
 
135
    if (index !== -1) {
136
      setActiveChats((prev) =>
137
        [...prev].map((chat) => {
138
          if (chat.id === entity.id) {
139
            return {
140
              ...chat,
141
              not_seen_messages: entity.not_seen_messages,
15765 stevensc 142
            };
15761 stevensc 143
          }
15765 stevensc 144
          return chat;
15761 stevensc 145
        })
15765 stevensc 146
      );
15761 stevensc 147
    }
15765 stevensc 148
  };
15761 stevensc 149
 
150
  const playNotifyAudio = (minimized = true) => {
151
    if (!isMuted && minimized) {
15765 stevensc 152
      notifyAudio.play();
15761 stevensc 153
    }
15765 stevensc 154
  };
15761 stevensc 155
 
156
  const handleMute = () => {
15765 stevensc 157
    setIsMuted(!isMuted);
15761 stevensc 158
    if (isMuted) {
15765 stevensc 159
      notifyAudio.play();
15761 stevensc 160
    }
15765 stevensc 161
  };
15761 stevensc 162
 
163
  useEffect(() => {
15765 stevensc 164
    if (!loading) setTimeout(() => heartBeat(), 2000);
165
  }, [loading]);
15761 stevensc 166
 
167
  useEffect(() => {
168
    if (pendingConversation) {
169
      const pendingChat = contacts.find(
170
        (contact) => contact.url_send === pendingConversation
15765 stevensc 171
      );
15761 stevensc 172
 
173
      if (pendingChat) {
15765 stevensc 174
        handleOpenConversation(pendingChat);
175
        setPendingConversation("");
15761 stevensc 176
      }
177
    }
15765 stevensc 178
  }, [pendingConversation, contacts]);
15761 stevensc 179
 
180
  useEffect(() => {
15765 stevensc 181
    emojione.imageType = "png";
182
    emojione.sprites = false;
183
    emojione.ascii = true;
184
    emojione.imagePathPNG = emojiOnePath;
185
  }, []);
15761 stevensc 186
 
15765 stevensc 187
  if (window.innerWidth < 1000 || window.location.pathname === "/chat")
188
    return null;
15761 stevensc 189
 
190
  return (
191
    <>
192
      <div className="chat-helper">
193
        <div
194
          className="subpanel_title"
195
          onClick={(e) =>
196
            e.currentTarget === e.target && setIsChatOpen(!isChatOpen)
197
          }
198
        >
199
          <a href="/chat" className="text-chat-title">
200
            {CHAT_LABELS.CHAT}
201
            <FiMaximize2 className="ml-3" />
202
          </a>
203
 
204
          <div className="subpanel_title-icons">
205
            <i
206
              className={`icon ${
15765 stevensc 207
                isMuted ? "icon-volume-off" : "icon-volume-2"
15761 stevensc 208
              } text-20`}
209
              onClick={handleMute}
210
            />
211
            <i
212
              className={`fa ${
15765 stevensc 213
                isChatOpen ? "fa-angle-down" : "fa-angle-up"
15761 stevensc 214
              } text-20`}
215
              onClick={() => setIsChatOpen(!isChatOpen)}
216
            />
217
          </div>
218
        </div>
219
        {isChatOpen && (
220
          <>
221
            <button className="action-btn" onClick={() => setShowModal(true)}>
222
              <AddIcon />
223
              {CHAT_LABELS.START_CONVERSATION}
224
            </button>
225
            <ContactsFilters
226
              dataset={contacts}
227
              selectConversation={(entity) => handleOpenConversation(entity)}
228
            />
229
          </>
230
        )}
231
      </div>
232
 
233
      <div className="active_chats-list">
234
        {activeChats.map((entity, index) => (
235
          <PersonalChat
236
            index={index}
237
            key={entity.id}
238
            entity={entity}
239
            not_seen_messages={entity.not_seen_messages}
240
            minimized={entity.minimized}
241
            onClose={handleCloseConversation}
242
            onMinimize={handleMinimizeConversation}
243
            onRead={handleReadConversation}
244
            timezones={timezones}
245
          />
246
        ))}
247
      </div>
248
      <ContactsModal show={showModal} onClose={() => setShowModal(false)} />
249
      <NotificationAlert />
250
    </>
15765 stevensc 251
  );
252
};
15761 stevensc 253
 
15765 stevensc 254
export default Chat;