Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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