Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

Rev Autor Línea Nro. Línea
5195 stevensc 1
/* eslint-disable camelcase */
3094 stevensc 2
/* eslint-disable react/prop-types */
5195 stevensc 3
import React, { useState, useRef, useEffect } from 'react'
4
import { axios } from '../../../utils'
5
import styled from 'styled-components'
6
import Emojione from './emojione/Emojione'
7
import SendFileModal from './send-file-modal/SendFileModal'
8
import ConfirmModal from '../../../shared/confirm-modal/ConfirmModal'
9
import MessageTemplate from './messageTemplate/MessageTemplate'
10
import { Modal } from 'react-bootstrap'
11
import { useForm } from 'react-hook-form'
12
import FormErrorFeedback from '../../../shared/form-error-feedback/FormErrorFeedback'
4119 stevensc 13
import 'react-datetime/css/react-datetime.css'
5195 stevensc 14
import Datetime from 'react-datetime'
15
import { addNotification } from '../../../redux/notification/notification.actions'
16
import Spinner from '../../../shared/loading-spinner/Spinner'
17
import { useDispatch } from 'react-redux'
4386 stevensc 18
import SearchIcon from '@mui/icons-material/Search'
5206 stevensc 19
import EmptySection from '../../../shared/empty-section/EmptySection'
1 www 20
 
21
const StyledChatHead = styled.div`
22
  .notify {
23
    animation: notify 2s infinite;
24
  }
25
 
26
  @keyframes notify {
27
    0% {
28
      background-color: unset;
29
    }
30
    50% {
31
      background-color: #00b0ff;
32
    }
33
    100% {
34
      background-color: unset;
35
    }
36
  }
5195 stevensc 37
`
1 www 38
 
39
const StyledShowOptions = styled.div`
40
  height: 342px;
41
  flex-direction: column;
5195 stevensc 42
  gap: 0.5rem;
1 www 43
  overflow-y: auto;
44
  position: relative;
45
  &.show {
46
    display: flex;
47
  }
48
  &.hide {
49
    display: none;
50
  }
51
  .optionBack {
52
    margin: 1rem 0 0.5rem 1rem;
53
    cursor: pointer;
54
  }
55
  .optionsTab {
56
    &__option {
57
      padding: 0.5rem;
58
      border-bottom: 1px solid #e2e2e2;
59
      cursor: pointer;
60
      &:hover {
61
        background-color: #e2e2e2;
62
      }
63
      &__icon {
64
        margin-right: 0.3rem;
65
      }
66
    }
67
  }
68
  .addPersonToGroupTab {
69
    display: flex;
70
    flex-direction: column;
71
    &__person {
72
      display: flex;
73
      justify-content: space-between;
74
      align-items: center;
75
      padding: 0.2rem 0.5rem;
76
      border-bottom: 1px solid #e2e2e2;
77
    }
78
  }
5195 stevensc 79
`
1 www 80
 
4119 stevensc 81
const PersonalChat = ({ entity, onClose, onMinimize, onRead, not_seen_messages, minimized, timezones }) => {
1 www 82
  const {
83
    id,
84
    image,
85
    name,
86
    online,
87
    type,
88
    url_get_all_messages,
89
    url_send,
90
    url_upload,
91
    profile,
92
    // group
93
    url_leave,
94
    url_delete,
95
    url_add_user_to_group,
96
    url_get_contact_group_list,
97
    url_get_contacts_availables_for_group,
4134 stevensc 98
    url_zoom
5195 stevensc 99
  } = entity
1 www 100
 
101
  // states
5195 stevensc 102
  const [messages, setMessages] = useState([])
103
  const [responseMessage, setResponseMessage] = useState(null)
104
  const [oldMessages, setOldMessages] = useState([])
105
  const [currentPage, setCurrentPage] = useState(1)
106
  const [pages, setPages] = useState(1)
107
  const [showOptions, setShowOptions] = useState(false)
108
  const [optionTab, setOptionTab] = useState('default')
109
  const [availableContactsToAdd, setAvailableContactsToAdd] = useState([])
110
  const [groupContactsList, setGroupContactsList] = useState([])
111
  const [confirmModalShow, setConfirmModalShow] = useState(false)
112
  const [showEmojiTab, setShowEmojiTab] = useState(false)
113
  const [shareFileModalShow, setShareFileModalShow] = useState(false)
114
  const [showConferenceModal, setShowConferenceModal] = useState(false)
115
  const [loading, setLoading] = useState(false)
116
  const [search, setSearch] = useState('')
1 www 117
 
4390 stevensc 118
  const filtredGroupList = groupContactsList.filter((conversation) => conversation.name.toLowerCase().includes(search.toLowerCase()))
4386 stevensc 119
 
1 www 120
  // refs
5195 stevensc 121
  const conversationListEl = useRef(null)
122
  const loader = useRef(null)
123
  const modalActionUrl = useRef('')
124
  const chatboxEl = useRef(null)
125
  const textAreaEl = useRef(null)
1 www 126
 
127
  // optionTabs
128
  const optionTabs = {
5195 stevensc 129
    add_person_to_group: 'add_person_to_group',
130
    group_contacts_list: 'group_contacts_list',
4116 stevensc 131
    meet: 'meet',
5195 stevensc 132
    default: 'default'
133
  }
1 www 134
 
135
  const handleActive = () => {
5195 stevensc 136
    onRead(entity)
137
    onMinimize(entity)
138
  }
1 www 139
 
140
  const handleGetMessages = async () => {
3122 stevensc 141
    setLoading(true)
5195 stevensc 142
    const response = await axios.get(url_get_all_messages)
143
    const resData = response.data
1 www 144
    if (!resData.success) {
5195 stevensc 145
      return ('ha ocurrido un error', resData)
1 www 146
    }
5195 stevensc 147
    const updatedMessages = [...resData.data.items].reverse()
1 www 148
    const newMessages = updatedMessages.reduce((acum, updatedMessage) => {
3089 stevensc 149
      if (messages.findIndex((message) => message.id === updatedMessage.id) === -1) {
5195 stevensc 150
        acum = [...acum, updatedMessage]
1 www 151
      }
5195 stevensc 152
      return acum
153
    }, [])
3089 stevensc 154
 
1 www 155
    if (newMessages.length > 0) {
5195 stevensc 156
      setMessages([...messages, ...newMessages])
3122 stevensc 157
      setLoading(false)
5195 stevensc 158
      setPages(resData.data.pages)
159
      scrollToBottom()
3090 stevensc 160
    } else {
5195 stevensc 161
      setMessages([...updatedMessages])
3122 stevensc 162
      setLoading(false)
1 www 163
    }
5195 stevensc 164
  }
1 www 165
 
166
  const handleLoadMore = async () => {
936 stevensc 167
    await axios.get(`${url_get_all_messages}?page=${currentPage}`)
1 www 168
      .then((response) => {
5195 stevensc 169
        const resData = response.data
1 www 170
        if (resData.success) {
171
          if (resData.data.page > 1) {
5195 stevensc 172
            const updatedOldMessages = [...resData.data.items].reverse()
173
            setOldMessages([...updatedOldMessages, ...oldMessages])
986 stevensc 174
            /* scrollDownBy(100); */
1 www 175
          }
176
        }
5195 stevensc 177
      })
178
  }
1 www 179
 
3122 stevensc 180
  const handleCloseChat = () => onClose(entity)
1 www 181
 
182
  const handleChatBoxKeyDown = async (e) => {
5195 stevensc 183
    if (e.key === 'Enter') {
184
      e.preventDefault()
185
      const message = e.target.value
186
      const formData = new FormData()
187
      formData.append('message', emojione.toShort(message))
2181 stevensc 188
      await axios.post(url_send, formData).then((response) => {
5195 stevensc 189
        const resData = response.data
2181 stevensc 190
        if (resData.success) {
2188 stevensc 191
          let newMessage = resData.data
2186 stevensc 192
 
193
          online
2188 stevensc 194
            ? newMessage = { ...newMessage, not_received: false }
195
            : newMessage = { ...newMessage, not_received: true }
2186 stevensc 196
 
2189 stevensc 197
          setMessages([...messages, newMessage])
2181 stevensc 198
        }
5195 stevensc 199
      })
200
      e.target.value = ''
2189 stevensc 201
      /* await handleGetMessages(); */
5195 stevensc 202
      setShowEmojiTab(false)
1778 stevensc 203
      setResponseMessage(null)
1 www 204
    }
5195 stevensc 205
  }
1 www 206
 
207
  const handleShowOptions = () => {
5195 stevensc 208
    onMinimize(entity, false)
209
    setShowOptions(!showOptions)
210
  }
1 www 211
 
212
  const handleChangeTab = (tab) => {
5195 stevensc 213
    setOptionTab(tab)
214
  }
1 www 215
 
216
  const handleAddPersonToGroup = async (id) => {
5195 stevensc 217
    const formData = new FormData()
218
    formData.append('uid', id)
1 www 219
    await axios.post(url_add_user_to_group, formData).then((response) => {
5195 stevensc 220
      const resData = response.data
1 www 221
      if (resData.success) {
5195 stevensc 222
        loadPersonsAvailable()
1 www 223
      }
5195 stevensc 224
    })
225
  }
1 www 226
 
227
  const handleConfirmModalAction = async () => {
3122 stevensc 228
    try {
3788 stevensc 229
      const { data } = await axios.post(modalActionUrl.current)
3122 stevensc 230
      if (!data.success) console.log('Error in confirm modal action')
3788 stevensc 231
      handleConfirmModalShow()
5195 stevensc 232
      onClose(entity)
3788 stevensc 233
      return
3122 stevensc 234
    } catch (error) {
235
      console.log(error)
236
    }
5195 stevensc 237
  }
1 www 238
 
239
  const handleObserver = (entities) => {
5195 stevensc 240
    const target = entities[0]
1 www 241
    if (target.isIntersecting) {
5195 stevensc 242
      setCurrentPage((prevState) => prevState + 1)
1 www 243
    }
5195 stevensc 244
  }
1 www 245
 
246
  const scrollToBottom = () => {
3056 stevensc 247
    if (conversationListEl.current) {
1 www 248
      conversationListEl.current.scrollTop =
5195 stevensc 249
        conversationListEl.current.scrollHeight * 9
1 www 250
    }
5195 stevensc 251
  }
1 www 252
 
253
  const handleShowEmojiTab = () => {
5195 stevensc 254
    setShowEmojiTab(!showEmojiTab)
1 www 255
    // smiley_tpl(`${id}`);
5195 stevensc 256
  }
1 www 257
 
258
  const handleClickEmoji = (e) => {
5195 stevensc 259
    const shortname = e.currentTarget.dataset.shortname
260
    const currentText = textAreaEl.current.value
261
    const cursorPosition = textAreaEl.current.selectionStart
262
    const textBehind = currentText.substring(0, cursorPosition)
263
    const textForward = currentText.substring(cursorPosition)
264
    const unicode = emojione.shortnameToUnicode(shortname)
265
    textAreaEl.current.value = `${textBehind}${unicode}${textForward}`
266
    textAreaEl.current.focus()
1 www 267
    textAreaEl.current.setSelectionRange(
268
      cursorPosition + unicode.length,
269
      cursorPosition + unicode.length
5195 stevensc 270
    )
271
  }
1 www 272
 
273
  // useEffect(() => {
274
  //   setMessages([...oldMessages, ...newMessages]);
275
  // }, [newMessages, oldMessages]);
276
 
277
  // getMessageOnMaximize and subscribe to infinite Loader
278
  useEffect(async () => {
5195 stevensc 279
    const options = {
3090 stevensc 280
      root: null,
5195 stevensc 281
      rootMargin: '20px',
282
      treshold: 1.0
283
    }
284
    const observer = new IntersectionObserver(handleObserver, options)
1 www 285
    if (!minimized) {
5195 stevensc 286
      await handleGetMessages()
1 www 287
      // loader observer
288
      if (loader.current) {
5195 stevensc 289
        observer.observe(loader.current)
1 www 290
      }
291
    }
292
    return () => {
293
      if (loader.current) {
5195 stevensc 294
        observer.unobserve(loader.current)
1 www 295
      }
5195 stevensc 296
    }
297
  }, [minimized])
1 www 298
 
299
  // LoadMore on change page
300
  useEffect(() => {
5195 stevensc 301
    let loadMore = () => handleLoadMore()
928 stevensc 302
    loadMore()
1 www 303
    return () => {
5195 stevensc 304
      loadMore = null
305
    }
306
  }, [currentPage])
1 www 307
 
308
  // getMessagesInterval
309
  useEffect(() => {
932 stevensc 310
    if (window.location.pathname === '/group/my-groups') {
38 steven 311
      const items = document.getElementsByClassName('sc-jSgupP')
5195 stevensc 312
      if (items && items.length > 0) { items[0].style.display = 'none' }
38 steven 313
    }
5195 stevensc 314
  }, [minimized])
3122 stevensc 315
 
316
  useEffect(() => {
5195 stevensc 317
    let timer
3119 stevensc 318
    if (!minimized && !loading) {
5195 stevensc 319
      timer = setTimeout(() => handleGetMessages(), 1000)
1 www 320
    }
3120 stevensc 321
    return () => {
5195 stevensc 322
      clearTimeout(timer)
323
    }
324
  }, [minimized, loading])
3122 stevensc 325
 
3788 stevensc 326
  const handleConfirmModalShow = () => setConfirmModalShow(!confirmModalShow)
1 www 327
 
3788 stevensc 328
  const handleConfirmModalAccept = () => handleConfirmModalAction()
1 www 329
 
330
  const handleShareFileModalShow = () => {
5195 stevensc 331
    setShareFileModalShow(!shareFileModalShow)
332
  }
1 www 333
 
1300 stevensc 334
  const handleResponseMessage = (element) => {
3059 stevensc 335
    element.mtype === 'text'
336
      ? setResponseMessage(element)
337
      : setResponseMessage({ ...element, m: 'Archivo adjunto' })
338
 
2765 stevensc 339
    textAreaEl.current && textAreaEl.current.focus()
5195 stevensc 340
  }
1300 stevensc 341
 
4116 stevensc 342
  const displayConferenceModal = () => setShowConferenceModal(!showConferenceModal)
4115 stevensc 343
 
1 www 344
  const messagesRender = () => {
345
    return (
346
      <React.Fragment>
5195 stevensc 347
        {currentPage < pages ? <li ref={loader}>Cargando...</li> : ''}
1 www 348
        {oldMessages.map((oldMessage) => (
3088 stevensc 349
          <MessageTemplate time={oldMessage.time} key={oldMessage.id} message={oldMessage} />
1 www 350
        ))}
1215 stevensc 351
        {messages.map((message, i) => {
5195 stevensc 352
          const currentTime = message.time
353
          const prevMessage = messages[i - 1]
2187 stevensc 354
 
5195 stevensc 355
          const dailys = ['mes', 'meses', 'semana', 'semanas', 'dia', 'dias', 'año', 'años']
356
          // const date = new Date(Date.now()).toLocaleDateString()
1215 stevensc 357
 
1216 stevensc 358
          if (prevMessage !== undefined) {
5195 stevensc 359
            const prevTime = messages[i - 1].time
2181 stevensc 360
 
1216 stevensc 361
            if (prevTime !== currentTime && dailys.includes(prevTime.split(' ')[1])) {
362
              return <>
2538 stevensc 363
                {/* <h2 className="text-center date-chat">{date}</h2> */}
1298 stevensc 364
                <MessageTemplate
3088 stevensc 365
                  key={message.id}
1298 stevensc 366
                  message={message}
3088 stevensc 367
                  time={message.time}
1300 stevensc 368
                  setResponseMessage={handleResponseMessage}
1298 stevensc 369
                  responseMessage={responseMessage}
370
                />
1216 stevensc 371
              </>
372
            }
1215 stevensc 373
          }
374
 
1300 stevensc 375
          return <MessageTemplate
3088 stevensc 376
            key={message.id}
1300 stevensc 377
            message={message}
3088 stevensc 378
            time={message.time}
1300 stevensc 379
            setResponseMessage={handleResponseMessage}
380
            responseMessage={responseMessage}
381
          />
1215 stevensc 382
        })}
1 www 383
      </React.Fragment>
5195 stevensc 384
    )
385
  }
1 www 386
 
387
  const optionRender = () => {
388
    switch (optionTab) {
389
      case optionTabs.add_person_to_group:
5195 stevensc 390
        return addPersonToGroupTab
1 www 391
      case optionTabs.group_contacts_list:
5195 stevensc 392
        return groupContactsListTab
4116 stevensc 393
      case optionTabs.meet:
5195 stevensc 394
        return meetingOptionsTab
1 www 395
      default:
5195 stevensc 396
        return optionsDefaultTab
1 www 397
    }
5195 stevensc 398
  }
1 www 399
 
400
  // useEffect for tabs changing
401
  useEffect(() => {
402
    switch (optionTab) {
403
      case optionTabs.add_person_to_group:
5195 stevensc 404
        loadPersonsAvailable()
405
        break
1 www 406
      case optionTabs.group_contacts_list:
5195 stevensc 407
        loadGroupContacts()
408
        break
1 www 409
    }
5195 stevensc 410
  }, [optionTab])
1 www 411
 
412
  const loadPersonsAvailable = async () => {
413
    await axios.get(url_get_contacts_availables_for_group).then((response) => {
5195 stevensc 414
      const resData = response.data
1 www 415
      if (resData.success) {
5195 stevensc 416
        setAvailableContactsToAdd(resData.data)
1 www 417
      }
5195 stevensc 418
    })
419
  }
1 www 420
 
421
  const loadGroupContacts = async () => {
422
    await axios.get(url_get_contact_group_list).then((response) => {
5195 stevensc 423
      const resData = response.data
1 www 424
      if (resData.success) {
5195 stevensc 425
        setGroupContactsList(resData.data)
1 www 426
      }
5195 stevensc 427
    })
428
  }
1 www 429
 
430
  const handleDeletePersonFromGroup = async (urlDeletePersonFromGroup) => {
431
    await axios.post(urlDeletePersonFromGroup).then((response) => {
5195 stevensc 432
      const resData = response.data
1 www 433
      if (resData.success) {
5195 stevensc 434
        loadGroupContacts()
1 www 435
      }
5195 stevensc 436
    })
437
  }
1 www 438
 
439
  const optionsDefaultTab = (
440
    <React.Fragment>
441
      <span className="optionBack" onClick={() => handleShowOptions()}>
442
        <i className="fa icon-arrow-left"></i>
443
      </span>
444
      <div className="optionsTab">
445
        <ul>
446
          {!!url_get_contact_group_list && (
447
            <li
448
              className="optionsTab__option"
449
              onClick={() => handleChangeTab(optionTabs.group_contacts_list)}
450
            >
451
              <span className="optionsTab__option__icon">
452
                <i className="fa fa-group"></i>
453
              </span>
454
              Integrantes
455
            </li>
456
          )}
457
          {!!url_add_user_to_group && (
458
            <li
459
              className="optionsTab__option"
460
              onClick={() => handleChangeTab(optionTabs.add_person_to_group)}
461
            >
462
              <span className="optionsTab__option__icon">
463
                <i className="fa fa-user-plus"></i>
464
              </span>
5206 stevensc 465
              {CHAT_LABELS.ADD_CONTACTS}
1 www 466
            </li>
467
          )}
4153 stevensc 468
          {
469
            url_zoom &&
470
            <li
471
              className="optionsTab__option"
472
              onClick={displayConferenceModal}
473
            >
474
              <span className="optionsTab__option__icon">
475
                <i className="fa fa-user-plus" />
476
              </span>
5206 stevensc 477
              {CHAT_LABELS.CREATE_CONFERENCE}
4153 stevensc 478
            </li>
479
          }
1 www 480
          {!!url_delete && (
481
            <li
482
              className="optionsTab__option"
5195 stevensc 483
              style={{ color: 'red' }}
1 www 484
              onClick={() => {
5195 stevensc 485
                handleConfirmModalShow()
486
                modalActionUrl.current = url_delete
1 www 487
              }}
488
            >
489
              <span className="optionsTab__option__icon">
490
                <i className="fa fa-trash"></i>
491
              </span>
492
              Eliminar grupo
493
            </li>
494
          )}
495
          {!!url_leave && (
496
            <li
497
              className="optionsTab__option"
5195 stevensc 498
              style={{ color: 'red' }}
1 www 499
              onClick={() => {
5195 stevensc 500
                handleConfirmModalShow()
501
                modalActionUrl.current = url_leave
1 www 502
              }}
503
            >
504
              <span className="optionsTab__option__icon">
505
                <i className="fa fa-user-times"></i>
506
              </span>
507
              Dejar grupo
508
            </li>
509
          )}
510
        </ul>
511
      </div>
512
    </React.Fragment>
5195 stevensc 513
  )
1 www 514
 
4115 stevensc 515
  const meetingOptionsTab = (
516
    <>
517
      <span className="optionBack" onClick={() => handleShowOptions()}>
518
        <i className="fa icon-arrow-left" />
519
      </span>
520
      <div className="optionsTab">
521
        <ul>
5206 stevensc 522
          <li className="optionsTab__option" onClick={displayConferenceModal}>
4115 stevensc 523
            <span className="optionsTab__option__icon">
524
              <i className="fa fa-user-plus" />
525
            </span>
5206 stevensc 526
            {CHAT_LABELS.CREATE_CONFERENCE}
4115 stevensc 527
          </li>
528
        </ul>
529
      </div>
530
    </>
5195 stevensc 531
  )
4115 stevensc 532
 
1 www 533
  const addPersonToGroupTab = (
5206 stevensc 534
    <>
535
      <span className="optionBack" onClick={() => handleChangeTab(optionTabs.default)}>
536
        <i className="fa icon-arrow-left" />
1 www 537
      </span>
538
      <div className="addPersonToGroupTab">
5206 stevensc 539
        !{availableContactsToAdd.length
540
        ? <EmptySection message={CHAT_LABELS.NOT_CONTACTS} align='left' />
541
        : availableContactsToAdd.map(({ image, name, id }) =>
1 www 542
            <div className="addPersonToGroupTab__person" key={id}>
2664 stevensc 543
              <div className="d-inline-flex" style={{ gap: '5px' }}>
2663 stevensc 544
                <img
545
                  className="chat-image img-circle pull-left"
546
                  height="36"
547
                  width="36"
548
                  src={image}
549
                  alt="image-image"
550
                />
551
                <div className="name">{name}</div>
552
              </div>
5206 stevensc 553
              <span className='cursor-pointer' onClick={() => handleAddPersonToGroup(id)}>
554
                <i className="fa fa-plus-circle" />
1 www 555
              </span>
556
            </div>
5206 stevensc 557
        )}
1 www 558
      </div>
5206 stevensc 559
    </>
5195 stevensc 560
  )
1 www 561
 
562
  const groupContactsListTab = (
4389 stevensc 563
    <>
4386 stevensc 564
      <span className="optionBack" onClick={() => handleChangeTab(optionTabs.default)}>
565
        <i className="fa icon-arrow-left" />
1 www 566
      </span>
4390 stevensc 567
      <div className='group__search'>
4386 stevensc 568
        <SearchIcon />
569
        <input
570
          type='text'
5206 stevensc 571
          placeholder={CHAT_LABELS.SEARCH}
4386 stevensc 572
          onChange={(e) => setSearch(e.target.value)}
573
        />
574
      </div>
1 www 575
      <div className="addPersonToGroupTab">
4389 stevensc 576
        {filtredGroupList.length
577
          ? filtredGroupList.map(({ image, name, url_remove_from_group, id }) => {
578
            return (
1 www 579
              <div className="addPersonToGroupTab__person" key={id}>
5195 stevensc 580
                <div style={{ display: 'flex', alignItems: 'center' }}>
1 www 581
                  <img
582
                    className="chat-image img-circle pull-left"
583
                    height="36"
584
                    width="36"
585
                    src={image}
586
                    alt="image-image"
587
                  />
588
                  <div className="name">{name}</div>
589
                </div>
4389 stevensc 590
                {url_remove_from_group &&
591
                  <span className="cursor-pointer" onClick={() => handleDeletePersonFromGroup(url_remove_from_group)}>
592
                    <i className="fa fa-user-times" />
1 www 593
                  </span>
4389 stevensc 594
                }
1 www 595
              </div>
596
            )
4389 stevensc 597
          })
5206 stevensc 598
          : <div className="addPersonToGroupTab__person">{CHAT_LABELS.NOT_CONTACTS}</div>
4389 stevensc 599
        }
1 www 600
      </div>
4389 stevensc 601
    </>
5195 stevensc 602
  )
1 www 603
 
604
  const userChat = (
4116 stevensc 605
    <>
3752 stevensc 606
      <div className="chatbox active-chat" style={{ display: 'block' }}>
1 www 607
        <div className="panel personal-chat">
608
          <StyledChatHead>
5195 stevensc 609
            <div className={`panel-heading chatboxhead ${not_seen_messages ? 'notify' : ''}`}>
1 www 610
              <div className="panel-title">
611
                <img
612
                  className="chat-image img-circle pull-left"
613
                  height="36"
614
                  width="36"
615
                  src={image}
616
                  alt="avatar-image"
617
                />
618
                <div className="header-elements">
3056 stevensc 619
                  <a href={profile} target="_blank" rel="noreferrer">
1 www 620
                    {name}
621
                  </a>
622
                  <br />
5195 stevensc 623
                  <small className={`status ${online ? 'Online' : 'Offline'}`}>
624
                    <b>{online ? 'En línea' : 'Desconectado'}</b>
1 www 625
                  </small>
5206 stevensc 626
 
1 www 627
                  <div className="pull-right options">
4115 stevensc 628
                    <div className="btn-group">
5206 stevensc 629
                      <i className="fa fa-gear" onClick={() => {
630
                        handleChangeTab(optionTabs.meet)
631
                        handleShowOptions()
632
                      }} />
1 www 633
                    </div>
4117 stevensc 634
                    <div className="btn-group">
5206 stevensc 635
                      <i className={'fa fa-minus-circle'} onClick={handleActive} />
1 www 636
                    </div>
4115 stevensc 637
                    <div className="btn-group">
5206 stevensc 638
                      <i className="fa fa-times-circle" onClick={handleCloseChat} />
1 www 639
                    </div>
640
                  </div>
5206 stevensc 641
 
1 www 642
                </div>
643
              </div>
644
            </div>
645
          </StyledChatHead>
646
          <div
647
            className="panel-body"
5195 stevensc 648
            style={{ display: !minimized ? 'block' : 'none' }}
1 www 649
          >
5195 stevensc 650
            <StyledShowOptions className={` ${showOptions ? 'show' : 'hide'}`}>
4116 stevensc 651
              {optionRender()}
652
            </StyledShowOptions>
1 www 653
            <div
654
              id="uploader_'+chatboxtitle+'"
5195 stevensc 655
              style={{ display: 'none', height: '342px' }}
1 www 656
            >
657
              <p>
658
                Your browser does not have Flash, Silverlight or HTML5 support.
659
              </p>
660
            </div>
4116 stevensc 661
            <div
662
              className="chat-conversation"
5195 stevensc 663
              style={{ position: 'relative', display: showOptions ? 'none' : 'block' }}
4116 stevensc 664
            >
1 www 665
              <div className="reverseChatBox" ref={conversationListEl}>
666
                <ul
667
                  className="conversation-list chatboxcontent"
668
                  id="resultchat_'+chatboxtitle+'"
669
                >
670
                  {messagesRender()}
671
                </ul>
672
              </div>
3604 stevensc 673
              <div className="wchat-footer wchat-chat-footer">
1301 stevensc 674
                <div id="chatFrom" className="chatFrom">
2577 stevensc 675
                  {
5195 stevensc 676
                    responseMessage &&
677
                    <div className={responseMessage ? 'resp_messages-container active' : 'resp_messages-container'}>
2577 stevensc 678
                      <span>{`Respondiendo a ${responseMessage.user_name}`}</span>
679
                      <p>{responseMessage.m}</p>
680
                    </div>
681
                  }
1 www 682
                  <div className="block-wchat">
683
                    <button
684
                      className="icon ti-clip attachment font-24 btn-attach btn-attach uploadFile"
685
                      id="uploadFile"
686
                      onClick={handleShareFileModalShow}
687
                    ></button>
688
                    <button
689
                      className="icon ti-face-smile font-24 btn-emoji"
690
                      id="toggle-emoji"
691
                      onClick={handleShowEmojiTab}
692
                    ></button>
693
                    <div className="input-container">
694
                      <div className="input-emoji">
695
                        <div
696
                          className="input-placeholder"
5195 stevensc 697
                          style={{ visibility: 'hidden', display: 'none' }}
1 www 698
                        >
5206 stevensc 699
                          {CHAT_LABELS.WRITE_A_MESSAGE}
1 www 700
                        </div>
701
                        <textarea
702
                          className="input chatboxtextarea"
703
                          id="chatboxtextarea"
704
                          name="chattxt"
5195 stevensc 705
                          style={{ resize: 'none', height: '20px' }}
5206 stevensc 706
                          placeholder={CHAT_LABELS.WRITE_A_MESSAGE}
1 www 707
                          onKeyDown={handleChatBoxKeyDown}
708
                          ref={textAreaEl}
3045 stevensc 709
                          onBlur={() => responseMessage && setResponseMessage(null)}
3122 stevensc 710
                          onFocus={() => not_seen_messages && onRead(entity)}
711
                        />
1 www 712
                      </div>
713
                    </div>
714
                  </div>
715
                </div>
5058 stevensc 716
 
717
                <div className="wchat-box-items-overlay-container">
5195 stevensc 718
                  <div className="target-emoji" style={{ display: showEmojiTab ? 'block' : 'none' }} id={`smileyPanel_${id}`}>
5058 stevensc 719
                    <Emojione onClickEmoji={handleClickEmoji} />
1 www 720
                  </div>
721
                </div>
5058 stevensc 722
 
1 www 723
              </div>
724
            </div>
725
          </div>
726
        </div>
727
      </div>
5052 stevensc 728
      <SendFileModal
729
        show={shareFileModalShow}
730
        onHide={() => setShareFileModalShow(false)}
731
        urlUpload={url_upload}
732
      />
4147 stevensc 733
      <ConferenceModal
734
        show={showConferenceModal}
735
        timezones={timezones}
736
        zoomUrl={url_zoom}
4149 stevensc 737
        onCreate={() => {
738
          handleShowOptions()
739
          displayConferenceModal()
740
        }}
4147 stevensc 741
      />
4116 stevensc 742
    </>
5195 stevensc 743
  )
1 www 744
 
745
  const groupChat = (
5206 stevensc 746
    <>
747
      <div className="chatbox active-chat " ref={chatboxEl}>
1 www 748
        <div className="panel personal-chat">
749
          <StyledChatHead>
5195 stevensc 750
            <div className={`panel-heading chatboxhead ${not_seen_messages ? 'notify' : ''}`}>
1 www 751
              <div className="panel-title-group">
752
                <img
753
                  className="chat-image img-circle pull-left"
754
                  height="36"
755
                  width="36"
756
                  src="/images/users-group.png"
757
                  alt="avatar-image"
758
                />
5206 stevensc 759
 
1 www 760
                <div className="header-elements">
761
                  <p>{name}</p>
5206 stevensc 762
 
1 www 763
                  <div className="pull-right options">
5206 stevensc 764
                    <div className="btn-group addUser" />
765
                    <i className="fa fa-gear" onClick={handleShowOptions} />
1 www 766
                  </div>
5206 stevensc 767
                  <div className="btn-group">
768
                    <i className='fa fa-minus-circle' onClick={handleActive} />
769
                  </div>
770
                  <div className="btn-group">
771
                    <i className="fa fa-times-circle" onClick={handleCloseChat} />
772
                  </div>
1 www 773
                </div>
5206 stevensc 774
 
1 www 775
              </div>
776
            </div>
777
          </StyledChatHead>
5206 stevensc 778
 
779
          <div className="panel-body" style={{ display: !minimized ? 'block' : 'none' }}>
5195 stevensc 780
            <StyledShowOptions className={` ${showOptions ? 'show' : 'hide'}`}>
1 www 781
              {optionRender()}
782
            </StyledShowOptions>
783
 
784
            <div
785
              className="chat-conversation"
786
              style={{
5195 stevensc 787
                display: showOptions ? 'none' : 'block',
788
                position: 'relative'
1 www 789
              }}
790
            >
791
              <div className="reverseChatBox" ref={conversationListEl}>
792
                <ul
793
                  className="conversation-list chatboxcontent"
794
                  id="resultchat_'+chatboxtitle+'"
795
                >
796
                  {messagesRender()}
797
                </ul>
798
              </div>
3604 stevensc 799
              <div className="wchat-footer wchat-chat-footer">
1 www 800
                <div id="chatFrom">
801
                  <div className="block-wchat">
802
                    <button
803
                      className="icon ti-clip attachment font-24 btn-attach btn-attach uploadFile"
804
                      id="uploadFile"
805
                      onClick={handleShareFileModalShow}
806
                    ></button>
807
                    <button
808
                      className="icon ti-face-smile font-24 btn-emoji"
809
                      id="toggle-emoji"
810
                      onClick={handleShowEmojiTab}
811
                    ></button>
812
                    <div className="input-container">
813
                      <div className="input-emoji">
814
                        <div
815
                          className="input-placeholder"
5195 stevensc 816
                          style={{ visibility: 'hidden', display: 'none' }}
1 www 817
                        >
5206 stevensc 818
                          {CHAT_LABELS.WRITE_A_MESSAGE}
1 www 819
                        </div>
820
                        <textarea
821
                          className="input chatboxtextarea"
822
                          name="chattxt"
5195 stevensc 823
                          style={{ resize: 'none', height: '20px' }}
5206 stevensc 824
                          placeholder={CHAT_LABELS.WRITE_A_MESSAGE}
1 www 825
                          onKeyDown={handleChatBoxKeyDown}
826
                          ref={textAreaEl}
3122 stevensc 827
                          onFocus={() => not_seen_messages && onRead(entity)}
3045 stevensc 828
                          onBlur={() => responseMessage && setResponseMessage(null)}
5206 stevensc 829
                        />
1 www 830
                        <input
831
                          id="to_uname"
832
                          name="to_uname"
833
                          value="'+chatboxtitle+'"
834
                          type="hidden"
835
                        />
836
                        <input
837
                          id="from_uname"
838
                          name="from_uname"
839
                          value="Beenny"
840
                          type="hidden"
841
                        />
842
                      </div>
843
                    </div>
844
                  </div>
845
                </div>
846
                <div className="wchat-box-items-positioning-container">
847
                  <div className="wchat-box-items-overlay-container">
848
                    <div
849
                      className="target-emoji"
5195 stevensc 850
                      style={{ display: showEmojiTab ? 'block' : 'none' }}
1 www 851
                    >
852
                      <div id={`smileyPanel_${id}`}>
853
                        <div>
854
                          <Emojione onClickEmoji={handleClickEmoji} />
855
                        </div>
856
                      </div>
857
                    </div>
858
                  </div>
859
                </div>
860
              </div>
861
            </div>
862
          </div>
863
        </div>
864
      </div>
865
      <ConfirmModal
866
        show={confirmModalShow}
867
        onClose={handleConfirmModalShow}
868
        onAccept={handleConfirmModalAccept}
869
      />
4152 stevensc 870
      <ConferenceModal
871
        show={showConferenceModal}
872
        timezones={timezones}
873
        zoomUrl={url_zoom}
874
        onCreate={() => {
875
          handleShowOptions()
876
          displayConferenceModal()
877
        }}
878
      />
5052 stevensc 879
      <SendFileModal
880
        show={shareFileModalShow}
881
        onHide={() => setShareFileModalShow(false)}
882
        urlUpload={url_upload}
883
      />
5206 stevensc 884
    </>
5195 stevensc 885
  )
1 www 886
 
887
  switch (type) {
5195 stevensc 888
    case 'user':
889
      return userChat
890
    case 'group':
891
      return groupChat
1 www 892
    default:
5195 stevensc 893
      break
1 www 894
  }
5195 stevensc 895
}
1 www 896
 
4115 stevensc 897
const StyleModal = ({
898
  title = 'Crea una conferencia',
899
  size = 'md',
900
  show = false,
901
  children
902
}) => {
903
  const [isShow, setIsShow] = useState(show)
904
 
4118 stevensc 905
  useEffect(() => {
906
    setIsShow(show)
907
  }, [show])
908
 
4115 stevensc 909
  const closeModal = () => setIsShow(false)
910
 
911
  return (
912
    <Modal
913
      show={isShow}
914
      onHide={closeModal}
5195 stevensc 915
      style={{ overflowY: 'scroll' }}
4115 stevensc 916
    >
917
      <Modal.Header closeButton>
918
        <Modal.Title>{title}</Modal.Title>
919
      </Modal.Header>
920
      <Modal.Body>
921
        {children}
922
      </Modal.Body>
923
    </Modal>
924
  )
925
}
926
 
5021 stevensc 927
export const ConferenceModal = ({
4128 stevensc 928
  show = false,
4134 stevensc 929
  timezones = {},
4147 stevensc 930
  zoomUrl = '',
931
  onCreate = () => null
4115 stevensc 932
}) => {
4130 stevensc 933
  const dt = new Date()
4136 stevensc 934
  const { handleSubmit, register, errors, reset } = useForm({ mode: 'all' })
4128 stevensc 935
  const [date, setDate] = useState({
5195 stevensc 936
    year: dt.toLocaleString('default', { year: 'numeric' }),
937
    month: dt.toLocaleString('default', { month: '2-digit' }),
938
    day: dt.toLocaleString('default', { day: '2-digit' })
4128 stevensc 939
  })
5195 stevensc 940
  const [time, setTime] = useState(dt.toLocaleString('es', { hour: 'numeric', minute: '2-digit', second: '2-digit' }))
4120 stevensc 941
  const [coferenceType, setConferenceType] = useState(1)
4140 stevensc 942
  const dispatch = useDispatch()
4115 stevensc 943
 
4120 stevensc 944
  const handleChange = (value) => setConferenceType(value)
945
 
4128 stevensc 946
  const handleDateTime = (value) => {
947
    setDate({
948
      ...date,
4134 stevensc 949
      year: new Intl.DateTimeFormat('es', { year: 'numeric' }).format(value),
950
      month: new Intl.DateTimeFormat('es', { month: '2-digit' }).format(value),
5195 stevensc 951
      day: new Intl.DateTimeFormat('es', { day: '2-digit' }).format(value)
4128 stevensc 952
    })
4143 stevensc 953
    setTime(new Intl.DateTimeFormat('es', { hour: 'numeric', minute: '2-digit', second: 'numeric' }).format(value))
4128 stevensc 954
  }
955
 
4139 stevensc 956
  const onSubmit = async (data) => {
957
    try {
958
      const formData = new FormData()
4134 stevensc 959
 
4139 stevensc 960
      Object.entries(data).forEach(([key, value]) => formData.append(key, value))
961
      formData.append('date', `${date.year}-${date.month}-${date.day}`)
4144 stevensc 962
      formData.append('time', time)
4139 stevensc 963
 
964
      const { data: response } = await axios.post(zoomUrl, formData)
965
 
4140 stevensc 966
      if (!response.success && typeof response.data === 'string') {
967
        dispatch(addNotification({ msg: response.data, style: 'danger' }))
968
        return
4139 stevensc 969
      }
970
 
4140 stevensc 971
      if (!response.success && typeof response.data === 'object') {
972
        Object.entries(response.data)
973
          .forEach(([key, value]) => {
974
            dispatch(addNotification({ msg: `${key}: ${value[0]}`, style: 'danger' }))
975
          })
976
        return
977
      }
978
 
4147 stevensc 979
      dispatch(addNotification({ msg: response.data, style: 'success' }))
980
      onCreate()
4139 stevensc 981
      reset()
982
    } catch (error) {
983
      console.log(`Error: ${error.message}`)
4140 stevensc 984
      return dispatch(addNotification({ msg: 'Ha ocurrido un error', style: 'danger' }))
4139 stevensc 985
    }
4115 stevensc 986
  }
987
 
988
  return (
5052 stevensc 989
    <StyleModal title='Crea una conferencia' show={show}>
4145 stevensc 990
      <form onSubmit={handleSubmit(onSubmit)} autoComplete="new-password">
4128 stevensc 991
        <div className="form-group">
992
          <label htmlFor="first_name">Título</label>
993
          <input
994
            type="text"
995
            name="title"
996
            className="form-control"
4133 stevensc 997
            maxLength={128}
5195 stevensc 998
            ref={register({ required: 'Por favor ingrese un título' })}
4128 stevensc 999
          />
5052 stevensc 1000
          {errors.title && <FormErrorFeedback>{errors.title.message}</FormErrorFeedback>}
4128 stevensc 1001
        </div>
1002
        <div className="form-group">
4133 stevensc 1003
          <label htmlFor="first_name">Descripción</label>
1004
          <input
1005
            type="text"
1006
            name="description"
1007
            className="form-control"
5195 stevensc 1008
            ref={register({ required: 'Por favor ingrese una descripción' })}
4133 stevensc 1009
          />
5052 stevensc 1010
          {errors.description && <FormErrorFeedback>{errors.description.message}</FormErrorFeedback>}
4133 stevensc 1011
        </div>
1012
        <div className="form-group">
4134 stevensc 1013
          <label htmlFor="timezone">Tipo de conferencia</label>
1014
          <select
1015
            name="type"
1016
            className="form-control"
1017
            onChange={({ target }) => handleChange(target.value)}
4137 stevensc 1018
            ref={register}
4134 stevensc 1019
          >
1020
            <option value='i'>
1021
              Inmediata
1022
            </option>
1023
            <option value='s'>
1024
              Programada
1025
            </option>
1026
          </select>
1027
        </div>
1028
        {
1029
          coferenceType === 's' &&
1030
          <div className="form-group">
1031
            <label htmlFor="timezone">Horario</label>
1032
            <Datetime
1033
              dateFormat="DD-MM-YYYY"
5017 stevensc 1034
              onChange={(e) => {
5019 stevensc 1035
                if (e.toDate) {
1036
                  handleDateTime(e.toDate())
5017 stevensc 1037
                }
1038
              }}
4134 stevensc 1039
              inputProps={{ className: 'form-control' }}
4138 stevensc 1040
              initialValue={Date.parse(new Date())}
4134 stevensc 1041
              closeOnSelect
1042
            />
1043
          </div>
1044
        }
1045
        <div className="form-group">
4128 stevensc 1046
          <label htmlFor="timezone">Zona horaria</label>
1047
          <select
1048
            className="form-control"
1049
            name="timezone"
5195 stevensc 1050
            ref={register({ required: 'Por favor elige una Zona horaria' })}
4128 stevensc 1051
          >
1052
            <option value="" hidden>
1053
              Zona horaria
1054
            </option>
1055
            {Object.entries(timezones).map(([key, value]) => (
1056
              <option value={key} key={key}>
1057
                {value}
4116 stevensc 1058
              </option>
4128 stevensc 1059
            ))}
1060
          </select>
1061
          {errors.timezone && <FormErrorFeedback>{errors.timezone.message}</FormErrorFeedback>}
4116 stevensc 1062
        </div>
4133 stevensc 1063
        <div className="form-group">
1064
          <label htmlFor="timezone">Duración</label>
1065
          <select
1066
            className="form-control"
1067
            name="duration"
4137 stevensc 1068
            ref={register}
4133 stevensc 1069
          >
1070
            <option value={5}>5-min</option>
1071
            <option value={10}>10-min</option>
1072
            <option value={15}>15-min</option>
1073
            <option value={20}>20-min</option>
1074
            <option value={25}>25-min</option>
1075
            <option value={30}>30-min</option>
1076
            <option value={35}>35-min</option>
1077
            <option value={40}>40-min</option>
1078
            <option value={45}>45-min</option>
1079
          </select>
1080
        </div>
1081
        <div className="form-group">
1082
          <label htmlFor="first_name">Contraseña de ingreso</label>
1083
          <input
1084
            type="password"
1085
            name="password"
1086
            className="form-control"
4137 stevensc 1087
            ref={register({
5195 stevensc 1088
              required: 'Por favor ingrese una contraseña',
1089
              maxLength: { value: 6, message: 'La contraseña debe tener al menos 6 digitos' }
4137 stevensc 1090
            })}
4133 stevensc 1091
          />
5052 stevensc 1092
          {errors.password && <FormErrorFeedback>{errors.password.message}</FormErrorFeedback>}
4115 stevensc 1093
        </div>
5052 stevensc 1094
        <button className="btn btn-primary" type="submit">
4116 stevensc 1095
          Crear
1096
        </button>
4115 stevensc 1097
      </form>
5206 stevensc 1098
    </StyleModal>
4115 stevensc 1099
  )
1100
}
1101
 
5195 stevensc 1102
export default React.memo(PersonalChat)