Proyectos de Subversion LeadersLinked - SPA

Rev

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

Rev Autor Línea Nro. Línea
1684 stevensc 1
import React, { useState } from 'react'
679 stevensc 2
import { Link } from 'react-router-dom'
517 stevensc 3
import { axios } from '../../utils'
4
import { useForm } from 'react-hook-form'
5
import { useDispatch } from 'react-redux'
6
import { addNotification } from '../../redux/notification/notification.actions'
1688 stevensc 7
import styled from 'styled-components'
517 stevensc 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'
5 stevensc 13
 
517 stevensc 14
import Options from '../UI/Option'
15
import Emojione from './emojione/Emojione'
16
import FileModal from '../modals/FileModal'
5 stevensc 17
 
1675 stevensc 18
const ChatContainer = styled.div`
5 stevensc 19
  background-color: var(--bg-color);
20
  border-radius: var(--border-radius);
21
  border: 1px solid var(--border-primary);
22
  height: 80vh;
23
  display: flex;
24
  flex-direction: column;
25
  flex-grow: 1;
440 andreina 26
  padding: 0px 0px !important;
517 stevensc 27
`
5 stevensc 28
 
29
const StyledChatHeader = styled.div`
30
  align-items: center;
31
  border-bottom: 1px solid var(--border-primary);
32
  display: flex;
33
  justify-content: center;
380 andreina 34
  padding: 1rem 0.5rem;
5 stevensc 35
  position: relative;
36
 
37
  & > button:first-child {
38
    position: absolute;
39
    left: 1rem;
40
    top: 50%;
41
    transform: translateY(-50%);
42
    display: inline-flex;
43
 
44
    @media (min-width: 768px) {
45
      display: none;
46
    }
47
  }
517 stevensc 48
`
5 stevensc 49
 
50
const StyledTitle = styled.h2`
517 stevensc 51
  font-size: 16px;
52
  font-weight: 600;
53
  width: fit-content;
54
  max-width: 20ch;
55
  text-align: center;
56
  color: #1d315c;
5 stevensc 57
 
58
  @media (min-width: 768px) {
59
    max-width: 30ch;
60
  }
517 stevensc 61
`
5 stevensc 62
 
63
const StyledForm = styled.form`
64
  border-top: 1px solid var(--border-primary);
65
  padding: 0.5rem;
66
  position: relative;
67
  display: flex;
68
  justify-content: center;
69
  align-items: center;
70
  gap: 0.5rem;
517 stevensc 71
`
5 stevensc 72
 
73
const StyledInput = styled.input`
74
  border: none;
75
  outline: none;
197 stevensc 76
  width: 100%;
5 stevensc 77
  padding: 0.5rem 1rem;
78
  border-radius: 30px;
197 stevensc 79
  background: var(--bg-color-secondary);
5 stevensc 80
 
81
  &:focus {
197 stevensc 82
    background: var(--bg-color-secondary);
5 stevensc 83
  }
517 stevensc 84
`
5 stevensc 85
 
86
const Header = ({ children, options = [], onClose }) => {
87
  return (
88
    <StyledChatHeader>
89
      <IconButton onClick={onClose}>
90
        <ArrowBackIcon />
91
      </IconButton>
92
      {children}
679 stevensc 93
      {!!options.length && <Options options={options} right='1rem' />}
5 stevensc 94
    </StyledChatHeader>
517 stevensc 95
  )
96
}
5 stevensc 97
 
98
const Title = ({ children, url }) => {
99
  if (!url) {
517 stevensc 100
    return <StyledTitle>{children}</StyledTitle>
5 stevensc 101
  }
102
 
103
  return (
517 stevensc 104
    <Link to={url} style={{ width: 'fit-content' }}>
5 stevensc 105
      <StyledTitle>{children}</StyledTitle>
517 stevensc 106
    </Link>
107
  )
108
}
5 stevensc 109
 
110
const SubmitForm = ({ sendUrl, uploadUrl, onSubmit: onComplete }) => {
517 stevensc 111
  const [showEmojione, setShowEmojione] = useState(false)
112
  const [isShowFileModal, setIsShowFileModal] = useState(false)
113
  const [isSending, setIsSending] = useState(false)
114
  const dispatch = useDispatch()
5 stevensc 115
 
517 stevensc 116
  const { handleSubmit, setValue, register, reset, getValues } = useForm()
5 stevensc 117
 
118
  const onSubmit = handleSubmit(({ message }) => {
1979 stevensc 119
    const formData = new FormData()
1718 stevensc 120
 
1979 stevensc 121
    formData.append('message', emojione.toShort(message))
5 stevensc 122
 
1979 stevensc 123
    axios.post(sendUrl, formData).then((response) => {
124
      const { success, data } = response.data
5 stevensc 125
 
1979 stevensc 126
      if (!success) {
127
        const errorMessage =
128
          typeof data === 'string' ? data : 'Ha ocurrido un error'
129
 
517 stevensc 130
        setShowEmojione(false)
1979 stevensc 131
        dispatch(addNotification({ style: 'danger', msg: errorMessage }))
132
        return
133
      }
134
 
135
      setShowEmojione(false)
136
      onComplete()
137
      reset()
138
    })
517 stevensc 139
  })
5 stevensc 140
 
141
  const sendFile = (file) => {
517 stevensc 142
    setIsSending(true)
1979 stevensc 143
    const formData = new FormData()
144
    formData.append('file', file)
5 stevensc 145
 
146
    axios
1979 stevensc 147
      .post(uploadUrl, formData)
5 stevensc 148
      .then(({ data: response }) => {
517 stevensc 149
        const { success, data } = response
5 stevensc 150
        if (!success) {
151
          const errorMessage =
517 stevensc 152
            typeof data === 'string' ? data : 'Ha ocurrido un error'
153
          dispatch(addNotification({ style: 'success', msg: errorMessage }))
154
          return
5 stevensc 155
        }
156
 
517 stevensc 157
        toggleFileModal()
158
        onComplete()
5 stevensc 159
      })
517 stevensc 160
      .finally(() => setIsSending(false))
161
  }
5 stevensc 162
 
163
  const toggleEmojione = () => {
517 stevensc 164
    setShowEmojione(!showEmojione)
165
  }
5 stevensc 166
 
167
  const toggleFileModal = () => {
517 stevensc 168
    setIsShowFileModal(!isShowFileModal)
169
  }
5 stevensc 170
 
171
  const onClickEmoji = (event) => {
517 stevensc 172
    const shortname = event.currentTarget.dataset.shortname
173
    const currentMessage = getValues('message')
5 stevensc 174
    // eslint-disable-next-line no-undef
517 stevensc 175
    const unicode = emojione.shortnameToUnicode(shortname)
176
    setValue('message', `${currentMessage}${unicode}`)
177
  }
5 stevensc 178
 
179
  return (
180
    <>
181
      <StyledForm onSubmit={onSubmit}>
182
        {showEmojione && <Emojione onClickEmoji={onClickEmoji} />}
230 stevensc 183
        <IconButton onClick={toggleFileModal}>
5 stevensc 184
          <AttachFileIcon />
185
        </IconButton>
186
        <IconButton onClick={toggleEmojione}>
187
          <InsertEmoticonIcon />
188
        </IconButton>
189
        <StyledInput
679 stevensc 190
          type='text'
191
          name='message'
192
          placeholder='Escribe un mensaje'
5 stevensc 193
          ref={register({ required: true })}
194
        />
679 stevensc 195
        <IconButton type='submit'>
5 stevensc 196
          <SendIcon />
197
        </IconButton>
198
      </StyledForm>
199
      <FileModal
200
        isShow={isShowFileModal}
201
        onHide={toggleFileModal}
202
        onComplete={sendFile}
203
        loading={isSending}
204
      />
205
    </>
517 stevensc 206
  )
207
}
5 stevensc 208
 
1675 stevensc 209
ChatContainer.Header = Header
210
ChatContainer.Title = Title
1684 stevensc 211
 
1675 stevensc 212
ChatContainer.SubmitForm = SubmitForm
5 stevensc 213
 
1675 stevensc 214
export default ChatContainer