Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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