Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 4154 | Rev 4389 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

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