Proyectos de Subversion LeadersLinked - Backend

Rev

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