Rev 16780 | 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 closeConversation = async (entity) => {
axios.post(entity.url_close).then((response) => {
const { success } = response.data
if (!success) {
console.log('Error in entity close')
return
}
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 closeConversation(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={closeConversation}
onMinimize={handleMinimizeConversation}
onRead={handleReadConversation}
timezones={timezones}
/>
))}
</div>
<ContactsModal show={showModal} onClose={() => setShowModal(false)} />
<NotificationAlert />
</>
)
}
export default Chat