Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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