Rev 5028 | Autoría | Ultima modificación | Ver Log |
/* eslint-disable react/prop-types */import React from "react";import { useState, useEffect } from "react";import { axios } from "../../utils";import { FiMaximize2 } from 'react-icons/fi'import AddIcon from '@mui/icons-material/Add'// Componentsimport NotificationAlert from "../../shared/notification/NotificationAlert";import PersonalChat from "./personal-chat/PersonalChat";import ContactsModal from "./components/ContactsModal";import ContactsList from "./components/ContactsList";const notifyAudio = new Audio("/audio/chat.mp3");const Chat = (props) => {const { defaultNetwork } = props// statesconst [contacts, setContacts] = useState([]);const [groups, setGroups] = 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 [activeTab, setActiveTab] = useState("user");const [search, setSearch] = useState('');const [pendingConversation, setPendingConversation] = useState('')const filtredContacts = contacts.filter(({ name }) => name.toLowerCase().includes(search.toLowerCase()))const filtredGroups = groups.filter(({ name }) => name.toLowerCase().includes(search.toLowerCase()))const handleEntities = entities => {let newUserContacts = [];let newGroups = [];entities.map((entity) => {if (entity.not_received_messages) handleNewMessage(entity)if (entity.not_seen_messages) handleNotSeenMessage(entity)if (entity.is_open) handleOpenConversation(entity, false);switch (entity.type) {case "user":newUserContacts = [...newUserContacts, entity];handleUpdateOnline(entity);break;case "group":newGroups = [...newGroups, entity];break;default:break;}});setContacts(newUserContacts);setGroups(newGroups);}const heartBeat = async () => {try {const { data } = await axios.get("/chat/heart-beat")if (data.success) {handleEntities(data.data)}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 handleCloseConversation = async (entity) => {const { data } = await axios.post(entity.url_close)if (!data.success) console.log('Error in entity close')setActiveChats(activeChats.filter(prevActiveChats => prevActiveChats.id !== entity.id))}const handleOpenConversation = async (entity, minimized = false) => {if (activeChats.length < 3 && !activeChats.some((el) => el.id === entity.id)) {setActiveChats([...activeChats, { ...entity, minimized: minimized }]);}if (activeChats.length >= 3 && !activeChats.some((el) => el.id === entity.id)) {await handleCloseConversation(activeChats[0])setActiveChats(prevActiveChats => [...prevActiveChats, { ...entity, minimized: 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();}};const handleChangeTab = (tab) => setActiveTab(tab)useEffect(() => {if (!loading) {const fetchData = async () => {setLoading(true)const entities = await heartBeat() || [];setLoading(false)return entities}setTimeout(() => {fetchData()}, "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 = props.emojiOnePath;}, []);if (window.innerWidth < 1000 || window.location.pathname === '/chat') return nullreturn (<><div className="chat-helper"><div className="subpanel_title" onClick={(e) => (e.currentTarget === e.target) && setIsChatOpen(!isChatOpen)}><a href="/chat" className="text-chat-title">Chat<FiMaximize2 className="ml-3" /></a><div className="subpanel_title-icons"><iclassName={`icon ${isMuted ? "icon-volume-off" : "icon-volume-2"} text-20`}onClick={handleMute}/><iclassName={`fa ${isChatOpen ? "fa-angle-down" : "fa-angle-up"} text-20`}onClick={() => setIsChatOpen(!isChatOpen)}/></div></div><divid="showhidechatlist"style={{ display: isChatOpen ? "grid" : "none" }}><div className="drupalchat_search_main chatboxinput"><inputclassName="drupalchat_searchinput live-search-box"id="live-search-box"type="text"name='search'value={search}onChange={(e) => setSearch(e.target.value)}/><i className="searchbutton fas fa-search" /></div>{defaultNetwork !== 'y' &&<divclassName="d-flex align-items-center cursor-pointer"style={{ gap: '.5rem', background: '#fff' }}onClick={() => setShowModal(true)}><AddIcon /><span>Iniciar conversación</span></div>}<div className="drupalchat_search_main chatboxinput"><button className={activeTab === 'user' && 'active'} onClick={() => handleChangeTab("user")}>Contactos</button><button className={activeTab === 'group' && 'active'} onClick={() => handleChangeTab("group")}>Grupos</button></div><ContactsListcontacts={filtredContacts}groups={filtredGroups}activeTab={activeChats}selectConversation={handleOpenConversation}/></div></div><div className="active_chats-list">{activeChats.map((entity, index) => (<PersonalChatindex={index}key={entity.id}entity={entity}not_seen_messages={entity.not_seen_messages}minimized={entity.minimized}onClose={handleCloseConversation}onMinimize={handleMinimizeConversation}onRead={handleReadConversation}timezones={props.timezones}/>))}</div><ContactsModalshow={showModal}setConversation={(url) => setPendingConversation(url)}/><NotificationAlert /></>)}export default Chat;