Rev 6921 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
import React, { useEffect, useRef, useState } from 'react'
import { axios } from '../../utils'
import { useForm } from 'react-hook-form'
import { useDispatch } from 'react-redux'
import { addNotification } from '../../redux/notification/notification.actions'
import parse from 'html-react-parser'
import styled from 'styled-components'
import SendIcon from '@mui/icons-material/Send'
import IconButton from '@mui/material/IconButton'
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
import AttachFileIcon from '@mui/icons-material/AttachFile'
import InsertEmoticonIcon from '@mui/icons-material/InsertEmoticon'
import Options from '../UI/Option'
import Emojione from './emojione/Emojione'
import FileModal from '../modals/FileModal'
const StyledChatContainer = styled.div`
background-color: $bg-color;
border-radius: $border-radius;
border: 1px solid $border-primary;
height: 80vh;
display: flex;
flex-direction: column;
`
const Chat = ({ children }) => {
return <StyledChatContainer>{children}</StyledChatContainer>
}
const Header = ({ children, options, onClose }) => {
return (
<div className="chat_header">
<IconButton onClick={onClose}>
<ArrowBackIcon />
</IconButton>
{children}
{options && <Options options={options} />}
</div>
)
}
const Title = ({ title, url }) => {
if (!url) {
return <h2>{title}</h2>
}
return (
<a href={url}>
<h2>{title}</h2>
</a>
)
}
const List = ({
messages,
pages,
currentPage,
onPagination,
scrollRef,
loading,
}) => {
const loadMoreEl = useRef()
useEffect(() => {
const observer = new IntersectionObserver(onPagination)
if (loadMoreEl.current) {
observer.observe(loadMoreEl.current)
}
return () => {
observer.disconnect()
}
}, [messages])
return (
<div className="messages_container" ref={scrollRef}>
<div className="message_wrapper">
{pages < currentPage && !loading && <p ref={loadMoreEl}>Cargando...</p>}
{messages.map((message) => (
<List.Message message={message} key={message.id} />
))}
</div>
</div>
)
}
const Message = ({ message }) => {
const senderName = (message) => {
if (message.type === 'group' && !message.u === 1) return message.user_name
}
const messagesContent = {
// eslint-disable-next-line no-undef
text: <p>{parse(emojione.shortnameToImage(message.m))}</p>,
image: <img src={message.m} alt="chat_image" />,
video: <video src={message.m} preload="none" controls />,
document: (
<img
className="pdf"
src="/storage/type/default/filename/pdf.png"
alt="pdf"
/>
),
}
return (
<div
className={`message_container ${message.u === 1 ? 'sent' : 'received'}`}
>
<span className="user_name">{senderName(message)}</span>
<div className={`message ${message.u === 1 ? 'sent' : 'received'}`}>
{messagesContent[message.mtype]}
<label className="message_time">
{!message.not_received && (
<i
className="fa fa-check"
style={message.seen ? { color: 'blue' } : { color: 'gray' }}
/>
)}
{message.time}
</label>
</div>
</div>
)
}
const SubmitForm = ({ sendUrl, uploadUrl, onSubmit: onComplete }) => {
const [showEmojione, setShowEmojione] = useState(false)
const [isShowFileModal, setIsShowFileModal] = useState(false)
const [isSending, setIsSending] = useState(false)
const dispatch = useDispatch()
const { handleSubmit, setValue, register, reset, getValues } = useForm()
const onSubmit = handleSubmit(({ message }) => {
const formData = new FormData()
// eslint-disable-next-line no-undef
formData.append('message', emojione.toShort(message))
axios.post(sendUrl, formData).then((response) => {
const { success, data } = response.data
if (!success) {
const errorMessage =
typeof data === 'string' ? data : 'Ha ocurrido un error'
setShowEmojione(false)
dispatch(addNotification({ style: 'danger', msg: errorMessage }))
return
}
setShowEmojione(false)
onComplete()
reset()
})
})
const sendFile = (file) => {
setIsSending(true)
const formData = new FormData()
formData.append('file', file)
axios
.post(uploadUrl, formData)
.then(({ data: response }) => {
const { success, data } = response
if (!success) {
const errorMessage =
typeof data === 'string' ? data : 'Ha ocurrido un error'
dispatch(addNotification({ style: 'success', msg: errorMessage }))
return
}
toggleFileModal()
onComplete()
})
.finally(() => setIsSending(false))
}
const toggleEmojione = () => {
setShowEmojione(!showEmojione)
}
const toggleFileModal = () => {
setIsShowFileModal(!isShowFileModal)
}
const onClickEmoji = (event) => {
const shortname = event.currentTarget.dataset.shortname
const currentMessage = getValues('message')
// eslint-disable-next-line no-undef
const unicode = emojione.shortnameToUnicode(shortname)
setValue('message', `${currentMessage}${unicode}`)
}
return (
<>
<form className="chat__input-container" onSubmit={onSubmit}>
{showEmojione && <Emojione onClickEmoji={onClickEmoji} />}
<IconButton onClick={toggleFileModal}>
<AttachFileIcon />
</IconButton>
<IconButton onClick={toggleEmojione}>
<InsertEmoticonIcon />
</IconButton>
<input
type="text"
name="message"
placeholder="Escribe un mensaje"
ref={register({ required: true })}
/>
<IconButton type="submit">
<SendIcon />
</IconButton>
</form>
<FileModal
isShow={isShowFileModal}
onHide={toggleFileModal}
onComplete={sendFile}
loading={isSending}
/>
</>
)
}
Chat.Header = Header
Chat.Title = Title
Chat.List = List
List.Message = Message
Chat.SubmitForm = SubmitForm
export default Chat