diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..130459b
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ }
+}
diff --git a/package.json b/package.json
index 6aee119..fde34d1 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,8 @@
"mobx-react": "^9.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-router-dom": "^6.21.1"
+ "react-router-dom": "^6.21.1",
+ "rxjs": "^7.8.1"
},
"devDependencies": {
"@types/react": "^18.2.15",
diff --git a/src/lib/websocketLib.js b/src/lib/websocketLib.js
index b91895b..c9d1b3e 100644
--- a/src/lib/websocketLib.js
+++ b/src/lib/websocketLib.js
@@ -1,21 +1,23 @@
// websocketLib.js
import { WebSocketSubject } from 'rxjs/webSocket';
import { retryWhen, delay, take, catchError } from 'rxjs/operators';
-import { throwError } from 'rxjs';
class WebSocketLib {
- constructor(url, authToken) {
+ constructor(url, authToken, protocol) {
this.url = url;
this.authToken = authToken;
+ this.protocol = protocol;
}
connect() {
this.socket$ = new WebSocketSubject({
url: this.url,
- protocol: this.authToken, // Using the protocol parameter for authentication
+ protocol: this.protocol, // Use protocol for message type
openObserver: {
next: () => {
console.log('Connection established');
+ // Send authentication message as soon as connection is established
+ this.socket$.next({ type: 'authenticate', token: this.authToken });
},
},
closeObserver: {
@@ -31,7 +33,7 @@ class WebSocketLib {
errors.pipe(
delay(1000), // Retry connection every 1 second
take(10), // Maximum of 10 retries
- catchError(error => throwError(`Failed to reconnect: ${error}`)) // Throw error after 10 failed retries
+ catchError(error => new Error(`Failed to reconnect: ${error}`)) // Throw error after 10 failed retries
)
)
)
diff --git a/src/main.jsx b/src/main.jsx
index 742a2c9..fc6b817 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -16,6 +16,8 @@ import DingdingQRCode from '@/views/DingdingQRCode'
import DingdingCallbak from '@/views/DingdingCallbak'
import ErrorPage from '@/views/ErrorPage'
+import Conversations from '@/views/Conversations/Components/ChatWindow';
+
configure({
useProxies: 'ifavailable',
enforceActions: 'observed',
@@ -30,18 +32,19 @@ const router = createBrowserRouter([
path: '/',
element: ,
errorElement: ,
- children: [
+ children: [
{ index: true, element: },
]
},
{
path: '/s',
element: ,
- children: [
+ children: [
{ index: true, element: },
{ path: 'order/follow', element: },
{ path: 'chat/history', element: },
{ path: 'sales/management', element: },
+ { path: 'order/chat', element: },
]
},
{
diff --git a/src/views/Conversations/App.jsx b/src/views/Conversations/App.jsx
new file mode 100644
index 0000000..e54cd21
--- /dev/null
+++ b/src/views/Conversations/App.jsx
@@ -0,0 +1,12 @@
+import Chat from './Index';
+// import 'antd/dist/reset.css';
+
+function App() {
+ return (
+
+
+
+ );
+}
+
+export default App;
diff --git a/src/views/Conversations/App1.jsx b/src/views/Conversations/App1.jsx
new file mode 100644
index 0000000..b1a985d
--- /dev/null
+++ b/src/views/Conversations/App1.jsx
@@ -0,0 +1,57 @@
+import { useState } from 'react';
+import { List, Input, Avatar, Button } from 'antd';
+
+const messages = [
+ {
+ sender: 'John Doe',
+ message: 'Hey!',
+ },
+ {
+ sender: 'Jane Doe',
+ message: 'Hi John!',
+ },
+];
+
+function App() {
+ const [message, setMessage] = useState('');
+
+ const sendMessage = () => {
+ // Update messages with new message data
+ const newMessage = {
+ sender: 'You',
+ message,
+ };
+ messages.push(newMessage);
+ setMessage('');
+ };
+
+ return (
+
+ (
+
+ }
+ title={message.sender}
+ description={message.message}
+ />
+
+ )}
+ />
+
+ setMessage(e.target.value)}
+ />
+
+
+
+ );
+}
+
+export default App;
diff --git a/src/views/Conversations/Chat.css b/src/views/Conversations/Chat.css
new file mode 100644
index 0000000..7d22a0c
--- /dev/null
+++ b/src/views/Conversations/Chat.css
@@ -0,0 +1,28 @@
+.chat-layout {
+ height: 100vh;
+}
+
+.chat-sider {
+ overflow: auto;
+}
+
+.chat-content {
+ padding: 24px;
+ overflow: auto;
+}
+
+.chat-input {
+ position: fixed;
+ bottom: 0;
+ width: calc(100% - 300px);
+ display: flex;
+ padding: 24px;
+}
+
+.chat-input .ant-input {
+ margin-right: 24px;
+}
+
+.chat-button {
+ height: 40px;
+}
\ No newline at end of file
diff --git a/src/views/Conversations/Components/ChatWindow.jsx b/src/views/Conversations/Components/ChatWindow.jsx
new file mode 100644
index 0000000..201f6ad
--- /dev/null
+++ b/src/views/Conversations/Components/ChatWindow.jsx
@@ -0,0 +1,38 @@
+
+import { Layout } from 'antd';
+import Messages from './Messages';
+import InputBox from './InputBox';
+import Conversations from './Conversations';
+import CustomerProfile from './CustomerProfile';
+
+const {Sider, Content } = Layout;
+
+const CList = [
+ { name: 'Customer_1', label: 'Customer_1', key: 'Customer_1', value: 'Customer_1' },
+ { name: 'Customer_2', label: 'Customer_2', key: 'Customer_2', value: 'Customer_2' },
+ { name: 'Customer_3', label: 'Customer_3', key: 'Customer_3', value: 'Customer_3' },
+ { name: 'Customer_4', label: 'Customer_4', key: 'Customer_4', value: 'Customer_4' },
+];
+function ChatWindow() {
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ChatWindow;
diff --git a/src/views/Conversations/Components/Conversations.jsx b/src/views/Conversations/Components/Conversations.jsx
new file mode 100644
index 0000000..020bc15
--- /dev/null
+++ b/src/views/Conversations/Components/Conversations.jsx
@@ -0,0 +1,31 @@
+import { List, Avatar } from 'antd';
+import PropTypes from 'prop-types';
+
+const ColorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
+function Conversations({ conversations }) {
+ return (
+ (
+
+
+ {item.name}
+
+ }
+ title={item.name}
+ />
+
+ )}
+ />
+ );
+}
+Conversations.propTypes = {
+ conversations: PropTypes.string.isRequired,
+};
+export default Conversations;
diff --git a/src/views/Conversations/Components/CustomerProfile.jsx b/src/views/Conversations/Components/CustomerProfile.jsx
new file mode 100644
index 0000000..961b524
--- /dev/null
+++ b/src/views/Conversations/Components/CustomerProfile.jsx
@@ -0,0 +1,8 @@
+import { Card } from 'antd';
+
+function CustomerProfile({ customer }) {
+ return {/* other profile details */};
+}
+CustomerProfile.propTypes = {
+};
+export default CustomerProfile;
diff --git a/src/views/Conversations/Components/InputBox.jsx b/src/views/Conversations/Components/InputBox.jsx
new file mode 100644
index 0000000..a665e8b
--- /dev/null
+++ b/src/views/Conversations/Components/InputBox.jsx
@@ -0,0 +1,22 @@
+
+import { Input, Button } from 'antd';
+
+function InputBox({ onSend }) {
+
+ function handleSend() {
+ // Logic to get message and call onSend
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default InputBox;
diff --git a/src/views/Conversations/Components/Messages.jsx b/src/views/Conversations/Components/Messages.jsx
new file mode 100644
index 0000000..49d071c
--- /dev/null
+++ b/src/views/Conversations/Components/Messages.jsx
@@ -0,0 +1,21 @@
+
+import { List, Avatar } from 'antd';
+
+function Messages({ messages }) {
+ return (
+ (
+
+ {message.sender[0]}}
+ title={message.sender}
+ />
+ {message.text}
+
+ )}
+ />
+ );
+}
+
+export default Messages;
diff --git a/src/views/Conversations/Index.jsx b/src/views/Conversations/Index.jsx
new file mode 100644
index 0000000..92b3c60
--- /dev/null
+++ b/src/views/Conversations/Index.jsx
@@ -0,0 +1,54 @@
+import { Layout, List, Input, Button } from 'antd';
+import './Chat.css';
+
+const { Sider, Content } = Layout;
+const { TextArea } = Input;
+
+const Chat = () => {
+ const channels = ['Channel 1', 'Channel 2'];
+ const messages = [
+ { user: 'User 1', text: 'Hello!' },
+ { user: 'User 2', text: 'Hi!' },
+ ];
+
+ return (
+
+
+ Channels}
+ bordered
+ dataSource={channels}
+ renderItem={item => (
+
+ {item}
+
+ )}
+ />
+
+
+
+ (
+
+
+
+ )}
+ />
+
+
+
+
+
+
+
+ );
+}
+
+export default Chat;
diff --git a/src/views/Conversations/Index2.jsx b/src/views/Conversations/Index2.jsx
new file mode 100644
index 0000000..9a34d2a
--- /dev/null
+++ b/src/views/Conversations/Index2.jsx
@@ -0,0 +1,35 @@
+import { useContext } from 'react';
+import { observer } from 'mobx-react';
+import { Table } from 'antd';
+import WebSocketLib from '@/lib/websocketLib';
+
+const CList = [
+ { name: 'Customer_1', label: 'Customer_1', key: 'Customer_1', value: 'Customer_1' },
+ { name: 'Customer_2', label: 'Customer_2', key: 'Customer_2', value: 'Customer_2' },
+ { name: 'Customer_3', label: 'Customer_3', key: 'Customer_3', value: 'Customer_3' },
+ { name: 'Customer_4', label: 'Customer_4', key: 'Customer_4', value: 'Customer_4' },
+];
+
+// Assume we have an array of customer URLs and their corresponding auth tokens
+const customers = [
+ { url: 'ws://202.103.68.144:8888/whatever/', authToken: 'customer1Token' },
+];
+
+ // Create a WebSocketLib instance for each customer
+ const connections = customers.map(customer => {
+ const wsLib = new WebSocketLib(customer.url, customer.authToken, 'WhatApp');
+ wsLib.connect();
+ return wsLib;
+ });
+
+ // Now, the agent can send a message to a specific customer like this:
+ connections[0].sendMessage('Hello, customer 1! '+ Date.now().toString(36));
+
+ // Or broadcast a message to all customers like this:
+ // connections.forEach(conn => conn.sendMessage('Hello, all customers!'));
+
+export default observer((props) => {
+ // const { } = useContext(stores_Context);
+ return <>>;
+});
+