Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 6921 | Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
6911 stevensc 1
import React, { useEffect, useRef, useState } from 'react'
2
import { axios } from '../../utils'
3
import { useForm } from 'react-hook-form'
4
import { useDispatch } from 'react-redux'
5
import { addNotification } from '../../redux/notification/notification.actions'
6
import parse from 'html-react-parser'
7
import styled from 'styled-components'
8
import SendIcon from '@mui/icons-material/Send'
9
import IconButton from '@mui/material/IconButton'
10
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
11
import AttachFileIcon from '@mui/icons-material/AttachFile'
12
import InsertEmoticonIcon from '@mui/icons-material/InsertEmoticon'
13
 
14
import Options from '../UI/Option'
15
import Emojione from './emojione/Emojione'
16
import FileModal from '../modals/FileModal'
17
 
18
const StyledChatContainer = styled.div`
19
  background-color: $bg-color;
20
  border-radius: $border-radius;
21
  border: 1px solid $border-primary;
22
  height: 80vh;
23
  display: flex;
24
  flex-direction: column;
25
`
26
 
27
const Chat = ({ children }) => {
28
  return <StyledChatContainer>{children}</StyledChatContainer>
29
}
30
 
31
const Header = ({ children, options, onClose }) => {
32
  return (
33
    <div className="chat_header">
34
      <IconButton onClick={onClose}>
35
        <ArrowBackIcon />
36
      </IconButton>
37
      {children}
38
      {options && <Options options={options} />}
39
    </div>
40
  )
41
}
42
 
43
const Title = ({ title, url }) => {
44
  if (!url) {
45
    return <h2>{title}</h2>
46
  }
47
 
48
  return (
49
    <a href={url}>
50
      <h2>{title}</h2>
51
    </a>
52
  )
53
}
54
 
55
const List = ({
56
  messages,
57
  pages,
58
  currentPage,
59
  onPagination,
60
  scrollRef,
61
  loading,
62
}) => {
63
  const loadMoreEl = useRef()
64
 
65
  useEffect(() => {
66
    const observer = new IntersectionObserver(onPagination)
67
 
68
    if (loadMoreEl.current) {
69
      observer.observe(loadMoreEl.current)
70
    }
71
 
72
    return () => {
73
      observer.disconnect()
74
    }
75
  }, [messages])
76
 
77
  return (
78
    <div className="messages_container" ref={scrollRef}>
79
      <div className="message_wrapper">
80
        {pages < currentPage && !loading && <p ref={loadMoreEl}>Cargando...</p>}
81
        {messages.map((message) => (
82
          <List.Message message={message} key={message.id} />
83
        ))}
84
      </div>
85
    </div>
86
  )
87
}
88
 
89
const Message = ({ message }) => {
90
  const senderName = (message) => {
91
    if (message.type === 'group' && !message.u === 1) return message.user_name
92
  }
93
 
94
  const messagesContent = {
95
    // eslint-disable-next-line no-undef
96
    text: <p>{parse(emojione.shortnameToImage(message.m))}</p>,
97
    image: <img src={message.m} alt="chat_image" />,
98
    video: <video src={message.m} preload="none" controls />,
99
    document: (
100
      <img
101
        className="pdf"
102
        src="/storage/type/default/filename/pdf.png"
103
        alt="pdf"
104
      />
105
    ),
106
  }
107
 
108
  return (
109
    <div
110
      className={`message_container ${message.u === 1 ? 'sent' : 'received'}`}
111
    >
112
      <span className="user_name">{senderName(message)}</span>
113
      <div className={`message ${message.u === 1 ? 'sent' : 'received'}`}>
114
        {messagesContent[message.mtype]}
115
        <label className="message_time">
116
          {!message.not_received && (
117
            <i
118
              className="fa fa-check"
119
              style={message.seen ? { color: 'blue' } : { color: 'gray' }}
120
            />
121
          )}
122
          {message.time}
123
        </label>
124
      </div>
125
    </div>
126
  )
127
}
128
 
129
const SubmitForm = ({ sendUrl, uploadUrl, onSubmit: onComplete }) => {
130
  const [showEmojione, setShowEmojione] = useState(false)
131
  const [isShowFileModal, setIsShowFileModal] = useState(false)
132
  const [isSending, setIsSending] = useState(false)
133
  const dispatch = useDispatch()
134
 
135
  const { handleSubmit, setValue, register, reset, getValues } = useForm()
136
 
137
  const onSubmit = handleSubmit(({ message }) => {
138
    const formData = new FormData()
139
    // eslint-disable-next-line no-undef
140
    formData.append('message', emojione.toShort(message))
141
 
142
    axios.post(sendUrl, formData).then((response) => {
143
      const { success, data } = response.data
144
 
145
      if (!success) {
146
        const errorMessage =
147
          typeof data === 'string' ? data : 'Ha ocurrido un error'
148
 
149
        setShowEmojione(false)
150
        dispatch(addNotification({ style: 'danger', msg: errorMessage }))
151
        return
152
      }
153
 
154
      setShowEmojione(false)
155
      onComplete()
156
      reset()
157
    })
158
  })
159
 
160
  const sendFile = (file) => {
161
    setIsSending(true)
162
    const formData = new FormData()
163
    formData.append('file', file)
164
 
165
    axios
166
      .post(uploadUrl, formData)
167
      .then(({ data: response }) => {
168
        const { success, data } = response
169
        if (!success) {
170
          const errorMessage =
171
            typeof data === 'string' ? data : 'Ha ocurrido un error'
172
          dispatch(addNotification({ style: 'success', msg: errorMessage }))
173
          return
174
        }
175
 
176
        toggleFileModal()
177
        onComplete()
178
      })
179
      .finally(() => setIsSending(false))
180
  }
181
 
182
  const toggleEmojione = () => {
183
    setShowEmojione(!showEmojione)
184
  }
185
 
186
  const toggleFileModal = () => {
187
    setIsShowFileModal(!isShowFileModal)
188
  }
189
 
190
  const onClickEmoji = (event) => {
191
    const shortname = event.currentTarget.dataset.shortname
192
    const currentMessage = getValues('message')
193
    // eslint-disable-next-line no-undef
194
    const unicode = emojione.shortnameToUnicode(shortname)
195
    setValue('message', `${currentMessage}${unicode}`)
196
  }
197
 
198
  return (
199
    <>
200
      <form className="chat__input-container" onSubmit={onSubmit}>
201
        {showEmojione && <Emojione onClickEmoji={onClickEmoji} />}
202
        <IconButton onClick={toggleFileModal}>
203
          <AttachFileIcon />
204
        </IconButton>
205
        <IconButton onClick={toggleEmojione}>
206
          <InsertEmoticonIcon />
207
        </IconButton>
208
        <input
209
          type="text"
210
          name="message"
211
          placeholder="Escribe un mensaje"
212
          ref={register({ required: true })}
213
        />
214
        <IconButton type="submit">
215
          <SendIcon />
216
        </IconButton>
217
      </form>
218
      <FileModal
219
        isShow={isShowFileModal}
220
        onHide={toggleFileModal}
221
        onComplete={sendFile}
222
        loading={isSending}
223
      />
224
    </>
225
  )
226
}
227
 
228
Chat.Header = Header
229
Chat.Title = Title
230
Chat.List = List
231
List.Message = Message
232
Chat.SubmitForm = SubmitForm
233
 
234
export default Chat