Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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