Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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