Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 5606 | Rev 5933 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
3710 stevensc 1
/* eslint-disable react/prop-types */
5242 stevensc 2
import React, { useEffect, useRef, useState } from 'react'
5253 stevensc 3
import { ArrowLeft } from '@mui/icons-material'
4
import { useDispatch } from 'react-redux'
5
import { addNotification } from '../../redux/notification/notification.actions'
6
import { axios, scrollToBottom } from '../../utils'
7
import { fetchMessages, getMessagesDifferences } from '../../services/chat'
8
import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded'
9
import SpeakerNotesOffRoundedIcon from '@mui/icons-material/SpeakerNotesOffRounded'
5185 stevensc 10
import EmptySection from '../../shared/empty-section/EmptySection'
11
import MessageBox from './MessageBox'
12
import MessageTemplate from './MessageTemplate'
5601 stevensc 13
import ConfirmModal from '../../shared/confirm-modal/ConfirmModal'
1 www 14
 
5239 stevensc 15
const DEFAULT_PAGES = { current: 1, last: 1 }
16
 
3074 stevensc 17
const Chatmail = ({
5185 stevensc 18
  selectedConversation = null,
5601 stevensc 19
  setConversation = () => null,
1741 stevensc 20
}) => {
5239 stevensc 21
  const [oldMessages, setOldMessages] = useState([])
22
  const [messages, setMessages] = useState([])
23
  const [pages, setPages] = useState(DEFAULT_PAGES)
24
  const [loading, setLoading] = useState(false)
5601 stevensc 25
  const [displayOptions, setDisplayOptions] = useState(false)
26
  const [isShowConfirm, setIsShowConfirm] = useState(false)
5185 stevensc 27
  const lastMessage = useRef(null)
5250 stevensc 28
  const messagesList = useRef(null)
5239 stevensc 29
  const dispatch = useDispatch()
835 stevensc 30
 
5248 stevensc 31
  const getMoreMessages = async (url = '', page = pages.current) => {
5239 stevensc 32
    try {
33
      setLoading(true)
34
      const response = await fetchMessages(url, page)
35
      if (!response.success) {
36
        const errorMessage = response.data
37
 
5601 stevensc 38
        dispatch(
39
          addNotification({ style: 'danger', msg: errorMessage.message })
40
        )
5239 stevensc 41
        return
42
      }
43
 
5254 stevensc 44
      if (response.pagination.current > 1) {
5601 stevensc 45
        setOldMessages((prevOldMessages) => [
46
          ...prevOldMessages,
47
          ...response.data,
48
        ])
5254 stevensc 49
      }
5601 stevensc 50
      setPages((prevPages) => ({
51
        ...prevPages,
52
        last: response.pagination.last,
53
      }))
5239 stevensc 54
 
5247 stevensc 55
      return
56
    } catch (error) {
57
      const errorMessage = new Error(error)
58
      console.log('Request canceled', errorMessage)
59
    } finally {
60
      setLoading(false)
61
    }
62
  }
63
 
64
  const hearBeat = async () => {
65
    try {
66
      setLoading(true)
5601 stevensc 67
      const response = await fetchMessages(
68
        selectedConversation.messages_link,
69
        1
70
      )
5247 stevensc 71
 
72
      if (!response.success) {
73
        const errorMessage = response.data
74
 
5601 stevensc 75
        dispatch(
76
          addNotification({ style: 'danger', msg: errorMessage.message })
77
        )
5247 stevensc 78
        return
5239 stevensc 79
      }
80
 
5247 stevensc 81
      const newMessages = getMessagesDifferences(messages, response.data)
82
 
5239 stevensc 83
      if (newMessages.length) {
5248 stevensc 84
        setMessages([...newMessages, ...messages])
5239 stevensc 85
        scrollToBottom()
86
      } else {
87
        setMessages(response.data)
88
      }
89
 
5601 stevensc 90
      setPages((prevPages) => ({
91
        ...prevPages,
92
        last: response.pagination.last,
93
      }))
5239 stevensc 94
    } catch (error) {
95
      const errorMessage = new Error(error)
96
      console.log('Request canceled', errorMessage)
97
    } finally {
98
      setLoading(false)
99
    }
100
  }
101
 
102
  const handleSend = async (sendUrl = '', message = {}) => {
103
    try {
104
      const formData = new FormData()
105
 
5601 stevensc 106
      Object.entries(message).forEach(([key, value]) =>
107
        formData.append(key, value)
108
      )
5239 stevensc 109
 
110
      const { data: response } = await axios.post(sendUrl, formData)
5601 stevensc 111
      setMessages((prev) => [response.data, ...prev])
5239 stevensc 112
    } catch (error) {
113
      const errorMessage = new Error(error)
114
      dispatch(addNotification({ style: 'danger', msg: errorMessage.message }))
115
    }
116
  }
117
 
118
  const loadMore = async () => {
119
    setPages((prevPages) => ({ ...prevPages, current: prevPages.current + 1 }))
120
  }
121
 
5601 stevensc 122
  const toggleConfirmModal = () => {
123
    setIsShowConfirm(!isShowConfirm)
124
  }
125
 
5603 stevensc 126
  const deleteConversation = () => {
5617 stevensc 127
    axios.post(selectedConversation.delete_link).then(({ data: response }) => {
128
      const { success, data } = response
5601 stevensc 129
 
5617 stevensc 130
      if (!success) {
131
        dispatch(addNotification({ style: 'danger', msg: data }))
132
        return
133
      }
5601 stevensc 134
 
5617 stevensc 135
      dispatch(addNotification({ style: 'success', msg: data }))
136
      setConversation(null)
137
    })
5601 stevensc 138
  }
139
 
5185 stevensc 140
  useEffect(() => {
5247 stevensc 141
    if (!loading && selectedConversation) setTimeout(() => hearBeat(), 3000)
5239 stevensc 142
  }, [loading, selectedConversation])
143
 
5242 stevensc 144
  useEffect(() => {
5248 stevensc 145
    if (messages) setMessages([])
5250 stevensc 146
    scrollToBottom(messagesList)
5247 stevensc 147
    setPages(DEFAULT_PAGES)
148
  }, [selectedConversation])
149
 
150
  useEffect(() => {
5601 stevensc 151
    if (selectedConversation)
152
      getMoreMessages(selectedConversation?.messages_link, pages.current)
5239 stevensc 153
  }, [pages.current])
154
 
5242 stevensc 155
  useEffect(() => {
5197 stevensc 156
    const observer = new IntersectionObserver(([entry]) => {
5252 stevensc 157
      if (entry.isIntersecting) {
158
        loadMore()
159
      }
5197 stevensc 160
    })
161
 
5253 stevensc 162
    if (lastMessage.current) {
163
      observer.observe(lastMessage.current)
164
    }
165
  }, [messages])
917 stevensc 166
 
5185 stevensc 167
  if (!selectedConversation) {
5601 stevensc 168
    return (
169
      <EmptySection
170
        message={LABELS.SELECT_CONVERSATION}
171
        Icon={<QuestionAnswerRoundedIcon />}
172
      />
173
    )
5185 stevensc 174
  }
175
 
176
  return (
5601 stevensc 177
    <div className="chat">
178
      <span className="icon-hide" onClick={() => setConversation(null)}>
5239 stevensc 179
        <ArrowLeft />
180
        {LABELS.RETURN}
181
      </span>
5601 stevensc 182
      <div className="d-flex align-items-center justify-content-center position-relative">
183
        <a href={selectedConversation.profile}>
184
          <h2 className="chat-header">{selectedConversation.name}</h2>
185
        </a>
186
        <div
187
          className="cursor-pointer d-flex align-items-center"
188
          style={{ position: 'absolute', right: '1rem' }}
189
        >
190
          <img
191
            src="/images/icons/options.png"
192
            className="cursor-pointer img-icon options"
193
            onClick={() => setDisplayOptions(!displayOptions)}
194
          />
195
          <div className={`feed-options ${displayOptions ? 'active' : ''}`}>
196
            <ul>
197
              <li>
198
                <button className="option-btn" onClick={toggleConfirmModal}>
199
                  <i className="fa fa-trash-o mr-1" />
200
                  Borrar
201
                </button>
202
              </li>
203
            </ul>
204
          </div>
205
          <ConfirmModal
206
            show={isShowConfirm}
207
            onClose={toggleConfirmModal}
208
            onAccept={deleteConversation}
209
            acceptLabel="Aceptar"
210
          />
211
        </div>
212
      </div>
5250 stevensc 213
      <div className="messages-line" ref={messagesList}>
5601 stevensc 214
        {messages.length ? (
215
          [...oldMessages, ...messages].map((element, index) => (
5185 stevensc 216
            <MessageTemplate
217
              key={index}
218
              message={element}
219
              date={element.date}
5601 stevensc 220
            />
221
          ))
222
        ) : (
223
          <EmptySection
224
            message={LABELS.NO_MESSAGE_CONVERSATION}
225
            Icon={<SpeakerNotesOffRoundedIcon />}
226
          />
227
        )}
228
        {pages.current < pages.last && (
229
          <hr ref={lastMessage} style={{ opacity: 0, margin: 0 }} />
230
        )}
5185 stevensc 231
      </div>
5601 stevensc 232
      <MessageBox
233
        onSend={handleSend}
234
        sendUrl={selectedConversation.send_link}
235
      />
5185 stevensc 236
    </div>
237
  )
3074 stevensc 238
}
239
 
5185 stevensc 240
export default Chatmail