Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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