hiesoftrd 1 gadu atpakaļ
vecāks
revīzija
9a8d5cdd42

BIN
frontend/src/assets/chat_notify.mp3


BIN
frontend/src/assets/dialogflow.png


BIN
frontend/src/assets/logo.png


BIN
frontend/src/assets/n8n.png


BIN
frontend/src/assets/planilha.xlsx


BIN
frontend/src/assets/sound.mp3


BIN
frontend/src/assets/sound.ogg


BIN
frontend/src/assets/typebot.jpg


BIN
frontend/src/assets/wa-background-dark.png


BIN
frontend/src/assets/wa-background.png


BIN
frontend/src/assets/webhook.png


+ 19 - 0
frontend/src/context/Auth/AuthContext.js

@@ -0,0 +1,19 @@
+import React, { createContext } from "react";
+
+import useAuth from "../../hooks/useAuth.js";
+
+const AuthContext = createContext();
+
+const AuthProvider = ({ children }) => {
+	const { loading, user, isAuth, handleLogin, handleLogout } = useAuth();
+
+	return (
+		<AuthContext.Provider
+			value={{ loading, user, isAuth, handleLogin, handleLogout }}
+		>
+			{children}
+		</AuthContext.Provider>
+	);
+};
+
+export { AuthContext, AuthProvider };

+ 17 - 0
frontend/src/context/ReplyingMessage/ReplyingMessageContext.js

@@ -0,0 +1,17 @@
+import React, { useState, createContext } from "react";
+
+const ReplyMessageContext = createContext();
+
+const ReplyMessageProvider = ({ children }) => {
+	const [replyingMessage, setReplyingMessage] = useState(null);
+
+	return (
+		<ReplyMessageContext.Provider
+			value={{ replyingMessage, setReplyingMessage }}
+		>
+			{children}
+		</ReplyMessageContext.Provider>
+	);
+};
+
+export { ReplyMessageContext, ReplyMessageProvider };

+ 173 - 0
frontend/src/context/Socket/SocketContext.js

@@ -0,0 +1,173 @@
+import { createContext } from "react";
+import openSocket from "socket.io-client";
+import jwt from "jsonwebtoken";
+
+class ManagedSocket {
+  constructor(socketManager) {
+    this.socketManager = socketManager;
+    this.rawSocket = socketManager.currentSocket;
+    this.callbacks = [];
+    this.joins = [];
+
+    this.rawSocket.on("connect", () => {
+      if (!this.rawSocket.recovered) {
+        const refreshJoinsOnReady = () => {
+          for (const j of this.joins) {
+            console.debug("refreshing join", j);
+            this.rawSocket.emit(`join${j.event}`, ...j.params);
+          }
+          this.rawSocket.off("ready", refreshJoinsOnReady);
+        };
+        for (const j of this.callbacks) {
+          this.rawSocket.off(j.event, j.callback);
+          this.rawSocket.on(j.event, j.callback);
+        }
+        
+        this.rawSocket.on("ready", refreshJoinsOnReady);
+      }
+    });
+  }
+  
+  on(event, callback) {
+    if (event === "ready" || event === "connect") {
+      return this.socketManager.onReady(callback);
+    }
+    this.callbacks.push({event, callback});
+    return this.rawSocket.on(event, callback);
+  }
+  
+  off(event, callback) {
+    const i = this.callbacks.findIndex((c) => c.event === event && c.callback === callback);
+    this.callbacks.splice(i, 1);
+    return this.rawSocket.off(event, callback);
+  }
+  
+  emit(event, ...params) {
+    if (event.startsWith("join")) {
+      this.joins.push({ event: event.substring(4), params });
+      console.log("Joining", { event: event.substring(4), params});
+    }
+    return this.rawSocket.emit(event, ...params);
+  }
+  
+  disconnect() {
+    for (const j of this.joins) {
+      this.rawSocket.emit(`leave${j.event}`, ...j.params);
+    }
+    this.joins = [];
+    for (const c of this.callbacks) {
+      this.rawSocket.off(c.event, c.callback);
+    }
+    this.callbacks = [];
+  }
+}
+
+class DummySocket {
+  on(..._) {}
+  off(..._) {}
+  emit(..._) {}
+  disconnect() {}
+}
+
+const SocketManager = {
+  currentCompanyId: -1,
+  currentUserId: -1,
+  currentSocket: null,
+  socketReady: false,
+
+  getSocket: function(companyId) {
+    let userId = null;
+    if (localStorage.getItem("userId")) {
+      userId = localStorage.getItem("userId");
+    }
+
+    if (!companyId && !this.currentSocket) {
+      return new DummySocket();
+    }
+
+    if (companyId && typeof companyId !== "string") {
+      companyId = `${companyId}`;
+    }
+
+    if (companyId !== this.currentCompanyId || userId !== this.currentUserId) {
+      if (this.currentSocket) {
+        console.warn("closing old socket - company or user changed");
+        this.currentSocket.removeAllListeners();
+        this.currentSocket.disconnect();
+        this.currentSocket = null;
+      }
+
+      let token = JSON.parse(localStorage.getItem("token"));
+      const { exp } = jwt.decode(token) ?? {};
+
+      if ( Date.now() >= exp*1000) {
+        console.warn("Expired token, reload after refresh");
+        setTimeout(() => {
+          window.location.reload();
+        },1000);
+        return new DummySocket();
+      }
+
+      this.currentCompanyId = companyId;
+      this.currentUserId = userId;
+      
+      if (!token) {
+        return new DummySocket();
+      }
+      
+      this.currentSocket = openSocket(process.env.REACT_APP_BACKEND_URL, {
+        transports: ["websocket"],
+        pingTimeout: 18000,
+        pingInterval: 18000,
+        query: { token },
+      });
+      
+      this.currentSocket.on("disconnect", (reason) => {
+        console.warn(`socket disconnected because: ${reason}`);
+        if (reason.startsWith("io ")) {
+          console.warn("tryng to reconnect", this.currentSocket);
+          
+          const { exp } = jwt.decode(token);
+          if ( Date.now()-180 >= exp*1000) {
+            console.warn("Expired token, reloading app");
+            window.location.reload();
+            return;
+          }
+
+          this.currentSocket.connect();
+        }        
+      });
+      
+      this.currentSocket.on("connect", (...params) => {
+        console.warn("socket connected", params);
+      })
+      
+      this.currentSocket.onAny((event, ...args) => {
+        console.debug("Event: ", { socket: this.currentSocket, event, args });
+      });
+      
+      this.onReady(() => {
+        this.socketReady = true;
+      });
+
+    }
+    
+    return new ManagedSocket(this);
+  },
+  
+  onReady: function( callbackReady ) {
+    if (this.socketReady) {
+      callbackReady();
+      return
+    }
+    
+    this.currentSocket.once("ready", () => {
+      callbackReady();
+    });
+  },
+
+};
+
+const SocketContext = createContext()
+
+export { SocketContext, SocketManager };

+ 26 - 0
frontend/src/context/Tickets/TicketsContext.js

@@ -0,0 +1,26 @@
+import React, { useState, useEffect, createContext } from "react";
+import { useHistory } from "react-router-dom";
+
+const TicketsContext = createContext();
+
+const TicketsContextProvider = ({ children }) => {
+	const [currentTicket, setCurrentTicket] = useState({ id: null, code: null });
+    const history = useHistory();
+
+    useEffect(() => {
+        if (currentTicket.id !== null) {
+            history.push(`/tickets/${currentTicket.uuid}`);
+        }
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [currentTicket])
+
+	return (
+		<TicketsContext.Provider
+			value={{ currentTicket, setCurrentTicket }}
+		>
+			{children}
+		</TicketsContext.Provider>
+	);
+};
+
+export { TicketsContext, TicketsContextProvider };

+ 17 - 0
frontend/src/context/WhatsApp/WhatsAppsContext.js

@@ -0,0 +1,17 @@
+import React, { createContext } from "react";
+
+import useWhatsApps from "../../hooks/useWhatsApps";
+
+const WhatsAppsContext = createContext();
+
+const WhatsAppsProvider = ({ children }) => {
+	const { loading, whatsApps } = useWhatsApps();
+
+	return (
+		<WhatsAppsContext.Provider value={{ whatsApps, loading }}>
+			{children}
+		</WhatsAppsContext.Provider>
+	);
+};
+
+export { WhatsAppsContext, WhatsAppsProvider };