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