Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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