Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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

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