Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 4145 | Rev 4149 | 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}
794
        onCreate={() => handleShowOptions()}
795
      />
4116 stevensc 796
    </>
1 www 797
  );
798
 
799
  const groupChat = (
800
    <React.Fragment>
801
      <div
3752 stevensc 802
        className="chatbox active-chat "
1 www 803
        ref={chatboxEl}
804
      >
805
        <div className="chatbox-icon">
806
          <div className="contact-floating red">
807
            <img className="chat-image img-circle pull-left" src={image} />
808
            <small className="unread-msg">2</small>
809
          </div>
810
        </div>
811
        <div className="panel personal-chat">
812
          <StyledChatHead>
3752 stevensc 813
            <div className={`panel-heading chatboxhead ${not_seen_messages ? "notify" : ""}`}>
1 www 814
              <div className="panel-title-group">
815
                <img
816
                  className="chat-image img-circle pull-left"
817
                  height="36"
818
                  width="36"
819
                  src="/images/users-group.png"
820
                  alt="avatar-image"
821
                />
822
                <div className="header-elements">
823
                  <p>{name}</p>
824
                  <br />
825
                  <div className="pull-right options">
826
                    <div
827
                      className="btn-group uploadFile"
828
                      id="uploadFile"
829
                      data-client="'+chatboxtitle+'"
830
                    >
831
                    </div>
3752 stevensc 832
                    <div className="btn-group">
1 www 833
                    </div>
834
                    <div
835
                      className="btn-group addUser"
836
                      data-client="8cb2a840-56c2-4f93-9cf1-27ad598acd8f"
837
                      data-name="Grupo de jesus"
838
                    >
839
                      <span>
840
                        <i
841
                          className="fa fa-gear"
842
                          onClick={handleShowOptions}
843
                        ></i>
844
                      </span>
845
                    </div>
3752 stevensc 846
                    <div className="btn-group">
1 www 847
                      <span>
848
                        <i
849
                          className={`fa fa-minus-circle`}
850
                          onClick={handleActive}
851
                        ></i>
852
                      </span>
853
                    </div>
3752 stevensc 854
                    <div className="btn-group">
1 www 855
                      <span>
856
                        <i
857
                          className="fa fa-times-circle"
858
                          onClick={handleCloseChat}
859
                        ></i>
860
                      </span>
861
                    </div>
862
                  </div>
863
                </div>
864
              </div>
865
            </div>
866
          </StyledChatHead>
867
          <div
868
            className="panel-body"
869
            style={{ display: !minimized ? "block" : "none" }}
870
          >
871
            <StyledShowOptions className={` ${showOptions ? "show" : "hide"}`}>
872
              {optionRender()}
873
            </StyledShowOptions>
874
 
875
            <div
876
              className="chat-conversation"
877
              style={{
878
                display: showOptions ? "none" : "block",
879
                position: "relative",
880
              }}
881
            >
882
              <div className="reverseChatBox" ref={conversationListEl}>
883
                <ul
884
                  className="conversation-list chatboxcontent"
885
                  id="resultchat_'+chatboxtitle+'"
886
                >
887
                  {messagesRender()}
888
                </ul>
889
              </div>
3604 stevensc 890
              <div className="wchat-footer wchat-chat-footer">
1 www 891
                <div id="chatFrom">
892
                  <div className="block-wchat">
893
                    <button
894
                      className="icon ti-clip attachment font-24 btn-attach btn-attach uploadFile"
895
                      id="uploadFile"
896
                      onClick={handleShareFileModalShow}
897
                    ></button>
898
                    <button
899
                      className="icon ti-face-smile font-24 btn-emoji"
900
                      id="toggle-emoji"
901
                      onClick={handleShowEmojiTab}
902
                    ></button>
903
                    <div className="input-container">
904
                      <div className="input-emoji">
905
                        <div
906
                          className="input-placeholder"
907
                          style={{ visibility: "hidden", display: "none" }}
908
                        >
909
                          Escribe un mensaje
910
                        </div>
911
                        <textarea
912
                          className="input chatboxtextarea"
913
                          id="chatboxtextarea"
914
                          name="chattxt"
915
                          style={{ resize: "none", height: "20px" }}
916
                          placeholder="Escribe un mensaje"
917
                          onKeyDown={handleChatBoxKeyDown}
918
                          ref={textAreaEl}
3122 stevensc 919
                          onFocus={() => not_seen_messages && onRead(entity)}
3045 stevensc 920
                          onBlur={() => responseMessage && setResponseMessage(null)}
1 www 921
                        ></textarea>
922
                        <input
923
                          id="to_uname"
924
                          name="to_uname"
925
                          value="'+chatboxtitle+'"
926
                          type="hidden"
927
                        />
928
                        <input
929
                          id="from_uname"
930
                          name="from_uname"
931
                          value="Beenny"
932
                          type="hidden"
933
                        />
934
                      </div>
935
                    </div>
936
                  </div>
937
                </div>
938
                <div className="wchat-box-items-positioning-container">
939
                  <div className="wchat-box-items-overlay-container">
940
                    <div
941
                      className="target-emoji"
942
                      style={{ display: showEmojiTab ? "block" : "none" }}
943
                    >
944
                      <div id={`smileyPanel_${id}`}>
945
                        <div>
946
                          <Emojione onClickEmoji={handleClickEmoji} />
947
                        </div>
948
                      </div>
949
                    </div>
950
                  </div>
951
                </div>
952
              </div>
953
            </div>
954
          </div>
955
        </div>
956
      </div>
957
      <ConfirmModal
958
        show={confirmModalShow}
959
        onClose={handleConfirmModalShow}
960
        onAccept={handleConfirmModalAccept}
961
      />
962
      {shareFileModal}
963
    </React.Fragment>
964
  );
965
 
966
  switch (type) {
967
    case "user":
968
      return userChat;
969
    case "group":
970
      return groupChat;
971
    default:
972
      break;
973
  }
974
};
975
 
4115 stevensc 976
const StyleModal = ({
977
  title = 'Crea una conferencia',
978
  size = 'md',
979
  show = false,
980
  children
981
}) => {
982
 
983
  const [isShow, setIsShow] = useState(show)
984
 
4118 stevensc 985
  useEffect(() => {
986
    setIsShow(show)
987
  }, [show])
988
 
4115 stevensc 989
  const closeModal = () => setIsShow(false)
990
 
991
  return (
992
    <Modal
993
      size={size}
994
      show={isShow}
995
      onHide={closeModal}
996
      style={{ overflowY: "scroll" }}
997
    >
998
      <Modal.Header closeButton>
999
        <Modal.Title>{title}</Modal.Title>
1000
      </Modal.Header>
1001
      <Modal.Body>
1002
        {children}
1003
      </Modal.Body>
1004
    </Modal>
1005
  )
1006
}
1007
 
1008
const ConferenceModal = ({
4128 stevensc 1009
  show = false,
4134 stevensc 1010
  timezones = {},
4147 stevensc 1011
  zoomUrl = '',
1012
  onCreate = () => null
4115 stevensc 1013
}) => {
1014
 
4130 stevensc 1015
  const dt = new Date()
4136 stevensc 1016
  const { handleSubmit, register, errors, reset } = useForm({ mode: 'all' })
4128 stevensc 1017
  const [date, setDate] = useState({
4130 stevensc 1018
    year: dt.toLocaleString("default", { year: "numeric" }),
1019
    month: dt.toLocaleString("default", { month: "2-digit" }),
1020
    day: dt.toLocaleString("default", { day: "2-digit" })
4128 stevensc 1021
  })
4145 stevensc 1022
  const [time, setTime] = useState(dt.toLocaleString("es", { hour: 'numeric', minute: '2-digit', second: '2-digit' }))
4120 stevensc 1023
  const [coferenceType, setConferenceType] = useState(1)
4140 stevensc 1024
  const dispatch = useDispatch()
4115 stevensc 1025
 
4120 stevensc 1026
  const handleChange = (value) => setConferenceType(value)
1027
 
4128 stevensc 1028
  const handleDateTime = (value) => {
1029
    setDate({
1030
      ...date,
4134 stevensc 1031
      year: new Intl.DateTimeFormat('es', { year: 'numeric' }).format(value),
1032
      month: new Intl.DateTimeFormat('es', { month: '2-digit' }).format(value),
1033
      day: new Intl.DateTimeFormat('es', { day: '2-digit' }).format(value),
4128 stevensc 1034
    })
4143 stevensc 1035
    setTime(new Intl.DateTimeFormat('es', { hour: 'numeric', minute: '2-digit', second: 'numeric' }).format(value))
4128 stevensc 1036
  }
1037
 
4139 stevensc 1038
  const onSubmit = async (data) => {
1039
    try {
1040
      const formData = new FormData()
4134 stevensc 1041
 
4139 stevensc 1042
      Object.entries(data).forEach(([key, value]) => formData.append(key, value))
1043
      formData.append('date', `${date.year}-${date.month}-${date.day}`)
4144 stevensc 1044
      formData.append('time', time)
4139 stevensc 1045
 
1046
      const { data: response } = await axios.post(zoomUrl, formData)
1047
 
4140 stevensc 1048
      if (!response.success && typeof response.data === 'string') {
1049
        dispatch(addNotification({ msg: response.data, style: 'danger' }))
1050
        return
4139 stevensc 1051
      }
1052
 
4140 stevensc 1053
      if (!response.success && typeof response.data === 'object') {
1054
        Object.entries(response.data)
1055
          .forEach(([key, value]) => {
1056
            dispatch(addNotification({ msg: `${key}: ${value[0]}`, style: 'danger' }))
1057
          })
1058
        return
1059
      }
1060
 
4147 stevensc 1061
      dispatch(addNotification({ msg: response.data, style: 'success' }))
1062
      onCreate()
4139 stevensc 1063
      reset()
1064
    } catch (error) {
1065
      console.log(`Error: ${error.message}`)
4140 stevensc 1066
      return dispatch(addNotification({ msg: 'Ha ocurrido un error', style: 'danger' }))
4139 stevensc 1067
    }
4115 stevensc 1068
  }
1069
 
1070
  return (
1071
    <StyleModal
1072
      title='Crea una conferencia'
1073
      size='md'
1074
      show={show}
1075
    >
4145 stevensc 1076
      <form onSubmit={handleSubmit(onSubmit)} autoComplete="new-password">
4128 stevensc 1077
        <div className="form-group">
1078
          <label htmlFor="first_name">Título</label>
1079
          <input
1080
            type="text"
1081
            name="title"
1082
            className="form-control"
4133 stevensc 1083
            maxLength={128}
4137 stevensc 1084
            ref={register({ required: "Por favor ingrese un título" })}
4128 stevensc 1085
          />
1086
          {errors.title && <FormErrorFeedback> {errors.title.message}</FormErrorFeedback>}
1087
        </div>
1088
        <div className="form-group">
4133 stevensc 1089
          <label htmlFor="first_name">Descripción</label>
1090
          <input
1091
            type="text"
1092
            name="description"
1093
            className="form-control"
4137 stevensc 1094
            ref={register({ required: "Por favor ingrese una descripción" })}
4133 stevensc 1095
          />
4138 stevensc 1096
          {errors.description && <FormErrorFeedback> {errors.description.message}</FormErrorFeedback>}
4133 stevensc 1097
        </div>
1098
        <div className="form-group">
4134 stevensc 1099
          <label htmlFor="timezone">Tipo de conferencia</label>
1100
          <select
1101
            name="type"
1102
            className="form-control"
1103
            onChange={({ target }) => handleChange(target.value)}
4137 stevensc 1104
            ref={register}
4134 stevensc 1105
          >
1106
            <option value='i'>
1107
              Inmediata
1108
            </option>
1109
            <option value='s'>
1110
              Programada
1111
            </option>
1112
          </select>
1113
        </div>
1114
        {
1115
          coferenceType === 's' &&
1116
          <div className="form-group">
1117
            <label htmlFor="timezone">Horario</label>
1118
            <Datetime
1119
              dateFormat="DD-MM-YYYY"
1120
              onChange={(e) => handleDateTime(e.toDate())}
1121
              inputProps={{ className: 'form-control' }}
4138 stevensc 1122
              initialValue={Date.parse(new Date())}
4134 stevensc 1123
              closeOnSelect
1124
            />
1125
          </div>
1126
        }
1127
        <div className="form-group">
4128 stevensc 1128
          <label htmlFor="timezone">Zona horaria</label>
1129
          <select
1130
            className="form-control"
1131
            name="timezone"
4137 stevensc 1132
            ref={register({ required: "Por favor elige una Zona horaria" })}
4128 stevensc 1133
          >
1134
            <option value="" hidden>
1135
              Zona horaria
1136
            </option>
1137
            {Object.entries(timezones).map(([key, value]) => (
1138
              <option value={key} key={key}>
1139
                {value}
4116 stevensc 1140
              </option>
4128 stevensc 1141
            ))}
1142
          </select>
1143
          {errors.timezone && <FormErrorFeedback>{errors.timezone.message}</FormErrorFeedback>}
4116 stevensc 1144
        </div>
4133 stevensc 1145
        <div className="form-group">
1146
          <label htmlFor="timezone">Duración</label>
1147
          <select
1148
            className="form-control"
1149
            name="duration"
4137 stevensc 1150
            ref={register}
4133 stevensc 1151
          >
1152
            <option value={5}>5-min</option>
1153
            <option value={10}>10-min</option>
1154
            <option value={15}>15-min</option>
1155
            <option value={20}>20-min</option>
1156
            <option value={25}>25-min</option>
1157
            <option value={30}>30-min</option>
1158
            <option value={35}>35-min</option>
1159
            <option value={40}>40-min</option>
1160
            <option value={45}>45-min</option>
1161
          </select>
1162
        </div>
1163
        <div className="form-group">
1164
          <label htmlFor="first_name">Contraseña de ingreso</label>
1165
          <input
1166
            type="password"
1167
            name="password"
1168
            className="form-control"
4137 stevensc 1169
            ref={register({
1170
              required: "Por favor ingrese una contraseña",
4145 stevensc 1171
              maxLength: { value: 6, message: "La contraseña debe tener al menos 6 digitos" }
4137 stevensc 1172
            })}
4133 stevensc 1173
          />
4139 stevensc 1174
          {errors.password && <FormErrorFeedback> {errors.password.message}</FormErrorFeedback>}
4115 stevensc 1175
        </div>
4136 stevensc 1176
        <button
1177
          className="btn btn-primary"
1178
          type="submit"
1179
        >
4116 stevensc 1180
          Crear
1181
        </button>
4115 stevensc 1182
      </form>
4133 stevensc 1183
    </StyleModal >
4115 stevensc 1184
  )
1185
}
1186
 
1187
export default React.memo(PersonalChat);