Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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