Proyectos de Subversion LeadersLinked - Backend

Rev

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