Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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