reducer context 管理conversation state
parent
fc556120ce
commit
4552d0ad58
@ -0,0 +1,129 @@
|
|||||||
|
|
||||||
|
import { groupBy } from '@/utils/utils';
|
||||||
|
|
||||||
|
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
|
||||||
|
|
||||||
|
const NAME_SPACE = 'CONVERSATION/';
|
||||||
|
export const initWebsocket = (socket) => ({
|
||||||
|
type: NAME_SPACE + 'INIT_WEBSOCKET',
|
||||||
|
payload: socket,
|
||||||
|
});
|
||||||
|
export const closeWebsocket0 = () => ({
|
||||||
|
type: NAME_SPACE + 'CLOSE_WEBSOCKET',
|
||||||
|
payload: null,
|
||||||
|
});
|
||||||
|
export const closeWebsocket = () => {};
|
||||||
|
|
||||||
|
export const receivedNewMessage = (targetId, message) => ({
|
||||||
|
type: NAME_SPACE + 'RECEIVED_NEW_MESSAGE',
|
||||||
|
payload: {
|
||||||
|
targetId,
|
||||||
|
message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const sentNewMessage = (message) => ({
|
||||||
|
type: NAME_SPACE + 'SENT_NEW_MESSAGE',
|
||||||
|
payload: {
|
||||||
|
targetId: message.conversationid,
|
||||||
|
message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const addError = (error) => {
|
||||||
|
return {
|
||||||
|
type: NAME_SPACE + 'ADD_ERROR',
|
||||||
|
payload: error,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const receivedTemplates = (data) => ({
|
||||||
|
type: NAME_SPACE + 'SET_TEMPLATE_LIST',
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const receivedConversationList = (data) => {
|
||||||
|
return {
|
||||||
|
type: NAME_SPACE + 'SET_CONVERSATION_LIST',
|
||||||
|
payload: data,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export const addConversationList = (data) => {
|
||||||
|
return {
|
||||||
|
type: NAME_SPACE + 'ADD_CONVERSATIONS',
|
||||||
|
payload: data,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export const updateConversationListItemNew = (message) => ({
|
||||||
|
type: NAME_SPACE + 'UPDATE_CONVERSATION_LIST_ITEM_NEW',
|
||||||
|
payload: message,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const receivedCustomerProfile = (data) => ({
|
||||||
|
type: NAME_SPACE + 'SET_CUSTOMER_ORDER_PROFILE',
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
export const setActiveConversations = (obj) => ({
|
||||||
|
type: NAME_SPACE + 'SET_ACTIVE_CONVERSATIONS',
|
||||||
|
payload: obj,
|
||||||
|
});
|
||||||
|
export const setCurrentConversation = (obj) => ({
|
||||||
|
type: NAME_SPACE + 'SET_CURRENT_CONVERSATION',
|
||||||
|
payload: obj,
|
||||||
|
});
|
||||||
|
export const updateMessageItem = (message) => ({
|
||||||
|
type: NAME_SPACE + 'UPDATE_SENT_MESSAGE_ITEM',
|
||||||
|
payload: message,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchTemplates = async () => {
|
||||||
|
const data = await fetchJSON(`${API_HOST}/listtemplates`);
|
||||||
|
const canUseTemplates = (data?.result?.items || [])
|
||||||
|
.filter((_t) => _t.status !== 'REJECTED')
|
||||||
|
.map((ele) => ({ ...ele, components: groupBy(ele.components, (_c) => _c.type.toLowerCase()) }));
|
||||||
|
return canUseTemplates;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchConversationsList = async (opisn) => {
|
||||||
|
const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn });
|
||||||
|
const _data = [];
|
||||||
|
// const _data = testConversations;
|
||||||
|
const list = [..._data, ...data.map((ele) => ({ ...ele, customer_name: ele.whatsapp_name.trim() }))];
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchCustomerProfile = async (colisn) => {
|
||||||
|
const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn });
|
||||||
|
const data = result?.[0] || {};
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function fetchJSON(url, data) {
|
||||||
|
let params = '';
|
||||||
|
let ifp = '';
|
||||||
|
if (data) {
|
||||||
|
params = new URLSearchParams(data).toString();
|
||||||
|
ifp = params ? '?' : ifp;
|
||||||
|
}
|
||||||
|
ifp = url.includes('?') ? '' : ifp;
|
||||||
|
const host = /^https?:\/\//i.test(url) ? '' : API_HOST;
|
||||||
|
const response = await fetch(`${host}${url}${ifp}${params}`);
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
export async function postJSON(url, obj) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(obj),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('fetch error:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
@ -1,334 +1,12 @@
|
|||||||
import { createContext, useContext, useState, useEffect, useRef } from 'react';
|
import {createContext, useContext} from 'react';
|
||||||
import { receivedMsgTypeMapped, sentMsgTypeMapped } from '@/lib/msgUtils';
|
|
||||||
import { groupBy, isEmpty, pick } from '@/utils/utils';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
|
|
||||||
export const ConversationContext = createContext();
|
export const ConversationContext = createContext();
|
||||||
export const useConversationContext = () => useContext(ConversationContext);
|
|
||||||
export async function fetchJSON(url, data) {
|
|
||||||
let params = '';
|
|
||||||
let ifp = '';
|
|
||||||
if (data) {
|
|
||||||
params = new URLSearchParams(data).toString();
|
|
||||||
ifp = params ? '?' : ifp;
|
|
||||||
}
|
|
||||||
ifp = url.includes('?') ? '' : ifp;
|
|
||||||
const host = /^https?:\/\//i.test(url) ? '' : ''; // HT_HOST;
|
|
||||||
const response = await fetch(`${host}${url}${ifp}${params}`);
|
|
||||||
return await response.json();
|
|
||||||
}
|
|
||||||
export async function postJSON(url, obj) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(obj),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
return await response.json();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('fetch error:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// const API_HOST = 'http://202.103.68.144:8888';
|
|
||||||
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
|
|
||||||
|
|
||||||
export const useConversations = ({loginUser, realtimeAPI}) => {
|
|
||||||
const { userId } = loginUser;
|
|
||||||
|
|
||||||
const [errors, setErrors] = useState([]);
|
|
||||||
const [messages, setMessages] = useState([]); // active conversation
|
|
||||||
const [activeConversations, setActiveConversations] = useState({}); // all active conversation
|
|
||||||
const [currentID, setCurrentID] = useState();
|
|
||||||
const [conversationsList, setConversationsList] = useState([]); // open conversations
|
|
||||||
const [currentConversation, setCurrentConversation] = useState({ sn: '', customer_name: '', coli_sn: '' });
|
|
||||||
const currentConversationRef = useRef(currentConversation);
|
|
||||||
useEffect(() => {
|
|
||||||
currentConversationRef.current = currentConversation;
|
|
||||||
}, [currentConversation]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(errors, 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
|
|
||||||
|
|
||||||
return () => {};
|
|
||||||
}, [errors])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
realtimeAPI.onError(addError.bind(null, 'Error'));
|
|
||||||
realtimeAPI.onMessage(handleMessage);
|
|
||||||
realtimeAPI.onCompletion(addError.bind(null, 'Not Connected to Server'));
|
|
||||||
realtimeAPI.keepAlive(); // Ping Server
|
|
||||||
|
|
||||||
// Cleanup function to remove the event listeners when the component is unmounted
|
|
||||||
return () => {
|
|
||||||
realtimeAPI.disconnect();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getConversationsList(); // todo: 和刷新订单会话页面有冲突
|
|
||||||
getTemplates();
|
|
||||||
return () => {};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (!currentConversation.id && conversationsList.length > 0) {
|
|
||||||
// switchConversation(conversationsList[0]);
|
|
||||||
// }
|
|
||||||
// return () => {};
|
|
||||||
// }, [conversationsList]);
|
|
||||||
|
|
||||||
const poseConversationItemClose = async (item) => {
|
|
||||||
const res = await postJSON(`${API_HOST}/closeconversation`, { opisn: userId, conversationid: item.sn });
|
|
||||||
}
|
|
||||||
|
|
||||||
const getConversationsList = async () => {
|
|
||||||
const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn: userId });
|
|
||||||
// const _data = [];
|
|
||||||
const _data = testConversations;
|
|
||||||
const list = [..._data, ...data.map(ele => ({...ele, customer_name: ele.whatsapp_name.trim()}))];
|
|
||||||
const dataMapped = list.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
|
||||||
setConversationsList(list);
|
|
||||||
setActiveConversations({...dataMapped, ...activeConversations});
|
|
||||||
console.log(list, dataMapped);
|
|
||||||
if (list && list.length) {
|
|
||||||
switchConversation(list[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const [templatesList, setTemplatesList] = useState([]);
|
|
||||||
const getTemplates = async () => {
|
|
||||||
const data = await fetchJSON(`${API_HOST}/listtemplates`);
|
|
||||||
const canUseTemplates = (data?.result?.items || []).filter((_t) => _t.status !== 'REJECTED').map((ele) => ({ ...ele, components: groupBy(ele.components, (_c) => _c.type.toLowerCase()) }));
|
|
||||||
setTemplatesList(canUseTemplates);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [customerOrderProfile, setCustomerProfile] = useState({});
|
|
||||||
const getCustomerProfile = async (colisn) => {
|
|
||||||
const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn });
|
|
||||||
const data = result?.[0] || {};
|
|
||||||
setCustomerProfile(data);
|
|
||||||
|
|
||||||
if (!isEmpty(data.conversation)) {
|
|
||||||
setConversationsList((pre) => [...data.conversations, ...pre]);
|
|
||||||
setCurrentConversation(data.conversation[0]);
|
|
||||||
const thisCMapped = data.conversation.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
|
||||||
setActiveConversations((pre) => ({ ...pre, ...thisCMapped }));
|
|
||||||
setMessages([]); // todo: 获取当前会话的历史消息
|
|
||||||
} else {
|
|
||||||
// reset chat window
|
|
||||||
setMessages([]);
|
|
||||||
if (isEmpty(data.contact?.[0]?.whatsapp_phone_number)) {
|
|
||||||
setCurrentConversation({ sn: '', customer_name: '', coli_sn: '' });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 加入新会话
|
|
||||||
const newChat = {
|
|
||||||
'sn': uuid(),
|
|
||||||
// 'opi_sn': 354,
|
|
||||||
'coli_sn': colisn,
|
|
||||||
'whatsapp_phone_number': data.contact[0].whatsapp_phone_number,
|
|
||||||
"last_received_time": '',
|
|
||||||
"last_send_time": '',
|
|
||||||
'unread_msg_count': 0,
|
|
||||||
'whatsapp_name': data.contact[0].name,
|
|
||||||
'customer_name': data.contact[0].name,
|
|
||||||
};
|
|
||||||
setConversationsList((pre) => [...pre, newChat]);
|
|
||||||
setActiveConversations((pre) => ({ ...pre, [`${newChat.sn}`]: [] }));
|
|
||||||
setCurrentConversation(pick(newChat, ['sn', 'coli_sn', 'whatsapp_phone_number', 'whatsapp_name', 'customer_name']));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const switchConversation = (cc) => {
|
|
||||||
setCurrentID(`${cc.sn}`);
|
|
||||||
setCurrentConversation({...cc, id: cc.sn, customer_name: cc.whatsapp_name.trim()});
|
|
||||||
|
|
||||||
if (isEmpty(cc.coli_sn) || cc.coli_sn === '0') {
|
|
||||||
setCustomerProfile({});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get customer profile when switching conversation
|
|
||||||
useEffect(() => {
|
|
||||||
console.log('currentConversation', currentConversation);
|
|
||||||
setCurrentID(currentConversation.sn);
|
|
||||||
setMessages([...(activeConversations[currentConversation.sn] || [])]);
|
|
||||||
return () => {};
|
|
||||||
}, [currentConversation]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* *****************************************************************************************************
|
|
||||||
* websocket --------------------------------------------------------------------------------------------
|
|
||||||
* *****************************************************************************************************
|
|
||||||
*/
|
|
||||||
const addError = (reason) => {
|
|
||||||
setErrors((prevErrors) => [...prevErrors, { reason }]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addMessageToConversations = (targetId, message) => {
|
|
||||||
setActiveConversations((prevList) => ({
|
|
||||||
...prevList,
|
|
||||||
[targetId]: [...(prevList[targetId] || []), message],
|
|
||||||
}));
|
|
||||||
// console.log('activeConversations', activeConversations);
|
|
||||||
if (targetId !== currentID) {
|
|
||||||
setConversationsList((prevList) => {
|
|
||||||
return prevList.map((ele) => {
|
|
||||||
if (ele.sn === targetId) {
|
|
||||||
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
|
|
||||||
}
|
|
||||||
return ele;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(messages, 'messages');
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, [messages])
|
|
||||||
|
|
||||||
|
|
||||||
const addMessage = (message) => {
|
|
||||||
addMessageToConversations(message.conversationid, message);
|
|
||||||
if (message.conversationid === currentID) {
|
|
||||||
setMessages((prevMessages) => [...prevMessages, message]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateMessage = (message) => {
|
|
||||||
let targetMsgs;
|
|
||||||
setMessages((prevMessages) => {
|
|
||||||
targetMsgs = prevMessages.map(ele => {
|
|
||||||
if (ele.id === ele.actionId && ele.actionId === message.actionId) {
|
|
||||||
return {...ele, id: message.id, status: message.status, dateString: message.dateString};
|
|
||||||
}
|
|
||||||
else if (ele.id === message.id) {
|
|
||||||
return {...ele, id: message.id, status: message.status, dateString: message.dateString};
|
|
||||||
}
|
|
||||||
return ele;
|
|
||||||
});
|
|
||||||
return targetMsgs;
|
|
||||||
});
|
|
||||||
// 更新会话中的消息
|
|
||||||
const targetId = message.conversationid; // currentConversationRef.current.sn;
|
|
||||||
setActiveConversations((prevList) => ({
|
|
||||||
...prevList,
|
|
||||||
[targetId]: targetMsgs,
|
|
||||||
}));
|
|
||||||
// 更新列表的时间
|
|
||||||
setConversationsList((prevList) => {
|
|
||||||
return prevList.map((ele) => {
|
|
||||||
if (ele.sn === targetId) {
|
|
||||||
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
|
|
||||||
}
|
|
||||||
return ele;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMessage = (data) => {
|
|
||||||
console.log('handleMessage------------------', );
|
|
||||||
/**
|
|
||||||
* ! event handlers in JavaScript capture the environment (including variables) at the time they are defined, not when they are executed.
|
|
||||||
*/
|
|
||||||
const { errcode, errmsg, result } = data;
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let resultType = result?.action || result.type;
|
|
||||||
if (errcode !== 0) {
|
|
||||||
// addError('Error Connecting to Server');
|
|
||||||
resultType = 'error';
|
|
||||||
}
|
|
||||||
console.log(resultType, 'result.type');
|
|
||||||
const msgObj = receivedMsgTypeMapped[resultType].getMsg(result);
|
|
||||||
const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj);
|
|
||||||
const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj);
|
|
||||||
console.log('msgRender msgUpdate', msgRender, msgUpdate);
|
|
||||||
if ( ['whatsapp.message.updated', 'message', 'error'].includes(resultType)) {
|
|
||||||
updateMessage(msgUpdate);
|
|
||||||
// return false;
|
|
||||||
}
|
|
||||||
if ( ! isEmpty(msgRender)) {
|
|
||||||
addMessage(msgRender);
|
|
||||||
}
|
|
||||||
console.log('handleMessage*******************', );
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMessage = (msgObj) => {
|
|
||||||
const contentToSend = sentMsgTypeMapped[msgObj.type].contentToSend(msgObj);
|
|
||||||
realtimeAPI.sendMessage({ ...contentToSend, opi_sn: userId });
|
|
||||||
const contentToRender = sentMsgTypeMapped[msgObj.type].contentToRender(msgObj);
|
|
||||||
console.log(contentToRender, 'contentToRender sendMessage------------------');
|
|
||||||
addMessage(contentToRender);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
errors,
|
|
||||||
messages,
|
|
||||||
conversationsList,
|
|
||||||
currentConversation,
|
|
||||||
sendMessage,
|
|
||||||
getConversationsList,
|
|
||||||
switchConversation,
|
|
||||||
templates: templatesList, // setTemplates, getTemplates,
|
|
||||||
customerOrderProfile, getCustomerProfile,
|
|
||||||
poseConversationItemClose
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const useConversationContext = () => useContext(ConversationContext);
|
||||||
|
|
||||||
|
|
||||||
|
export const ConversationStateContext = createContext();
|
||||||
|
export const ConversationDispatchContext = createContext();
|
||||||
|
|
||||||
// test:
|
export const useConversationState = () => useContext(ConversationStateContext);
|
||||||
const testConversations = [
|
export const useConversationDispatch = () => useContext(ConversationDispatchContext);
|
||||||
{
|
|
||||||
'sn': 3001,
|
|
||||||
'opi_sn': 354,
|
|
||||||
'coli_sn': 0,
|
|
||||||
'whatsapp_phone_number': '+8618777396951',
|
|
||||||
"last_received_time": new Date().toDateString(),
|
|
||||||
"last_send_time": new Date().toDateString(),
|
|
||||||
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
|
||||||
'whatsapp_name': 'LiaoYijun',
|
|
||||||
'customer_name': 'LiaoYijun',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'sn': 3002,
|
|
||||||
'opi_sn': 354,
|
|
||||||
'coli_sn': 0,
|
|
||||||
'whatsapp_phone_number': '+8613317835586',
|
|
||||||
"last_received_time": new Date().toDateString(),
|
|
||||||
"last_send_time": new Date().toDateString(),
|
|
||||||
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
|
||||||
'whatsapp_name': 'QinQianSheng',
|
|
||||||
'customer_name': 'QinQianSheng',
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// 'sn': 3003,
|
|
||||||
// 'opi_sn': 354,
|
|
||||||
// 'coli_sn': 240129003,
|
|
||||||
// 'whatsapp_phone_number': '+8618777396951',
|
|
||||||
// "last_received_time": new Date().toDateString(),
|
|
||||||
// "last_send_time": new Date().toDateString(),
|
|
||||||
// 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
|
||||||
// 'whatsapp_name': 'LeiYuanTing',
|
|
||||||
// },
|
|
||||||
];
|
|
||||||
|
@ -0,0 +1,334 @@
|
|||||||
|
import { createContext, useContext, useState, useEffect, useRef } from 'react';
|
||||||
|
import { receivedMsgTypeMapped, sentMsgTypeMapped } from '@/lib/msgUtils';
|
||||||
|
import { groupBy, isEmpty, pick } from '@/utils/utils';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
export const ConversationContext = createContext();
|
||||||
|
export const useConversationContext = () => useContext(ConversationContext);
|
||||||
|
export async function fetchJSON(url, data) {
|
||||||
|
let params = '';
|
||||||
|
let ifp = '';
|
||||||
|
if (data) {
|
||||||
|
params = new URLSearchParams(data).toString();
|
||||||
|
ifp = params ? '?' : ifp;
|
||||||
|
}
|
||||||
|
ifp = url.includes('?') ? '' : ifp;
|
||||||
|
const host = /^https?:\/\//i.test(url) ? '' : ''; // HT_HOST;
|
||||||
|
const response = await fetch(`${host}${url}${ifp}${params}`);
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
export async function postJSON(url, obj) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(obj),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('fetch error:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const API_HOST = 'http://202.103.68.144:8888';
|
||||||
|
const API_HOST = 'https://p9axztuwd7x8a7.mycht.cn/whatsapp_callback';
|
||||||
|
|
||||||
|
export const useConversations = ({loginUser, realtimeAPI}) => {
|
||||||
|
const { userId } = loginUser;
|
||||||
|
|
||||||
|
const [errors, setErrors] = useState([]);
|
||||||
|
const [messages, setMessages] = useState([]); // active conversation
|
||||||
|
const [activeConversations, setActiveConversations] = useState({}); // all active conversation
|
||||||
|
const [currentID, setCurrentID] = useState();
|
||||||
|
const [conversationsList, setConversationsList] = useState([]); // open conversations
|
||||||
|
const [currentConversation, setCurrentConversation] = useState({ sn: '', customer_name: '', coli_sn: '' });
|
||||||
|
const currentConversationRef = useRef(currentConversation);
|
||||||
|
useEffect(() => {
|
||||||
|
currentConversationRef.current = currentConversation;
|
||||||
|
}, [currentConversation]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(errors, 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee');
|
||||||
|
|
||||||
|
return () => {};
|
||||||
|
}, [errors])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
realtimeAPI.onError(addError.bind(null, 'Error'));
|
||||||
|
realtimeAPI.onMessage(handleMessage);
|
||||||
|
realtimeAPI.onCompletion(addError.bind(null, 'Not Connected to Server'));
|
||||||
|
realtimeAPI.keepAlive(); // Ping Server
|
||||||
|
|
||||||
|
// Cleanup function to remove the event listeners when the component is unmounted
|
||||||
|
return () => {
|
||||||
|
realtimeAPI.disconnect();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getConversationsList(); // todo: 和刷新订单会话页面有冲突
|
||||||
|
getTemplates();
|
||||||
|
return () => {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!currentConversation.id && conversationsList.length > 0) {
|
||||||
|
// switchConversation(conversationsList[0]);
|
||||||
|
// }
|
||||||
|
// return () => {};
|
||||||
|
// }, [conversationsList]);
|
||||||
|
|
||||||
|
const poseConversationItemClose = async (item) => {
|
||||||
|
const res = await postJSON(`${API_HOST}/closeconversation`, { opisn: userId, conversationid: item.sn });
|
||||||
|
}
|
||||||
|
|
||||||
|
const getConversationsList = async () => {
|
||||||
|
const { result: data } = await fetchJSON(`${API_HOST}/getconversations`, { opisn: userId });
|
||||||
|
// const _data = [];
|
||||||
|
const _data = testConversations;
|
||||||
|
const list = [..._data, ...data.map(ele => ({...ele, customer_name: ele.whatsapp_name.trim()}))];
|
||||||
|
const dataMapped = list.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
||||||
|
setConversationsList(list);
|
||||||
|
setActiveConversations({...dataMapped, ...activeConversations});
|
||||||
|
console.log(list, dataMapped);
|
||||||
|
if (list && list.length) {
|
||||||
|
switchConversation(list[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [templatesList, setTemplatesList] = useState([]);
|
||||||
|
const getTemplates = async () => {
|
||||||
|
const data = await fetchJSON(`${API_HOST}/listtemplates`);
|
||||||
|
const canUseTemplates = (data?.result?.items || []).filter((_t) => _t.status !== 'REJECTED').map((ele) => ({ ...ele, components: groupBy(ele.components, (_c) => _c.type.toLowerCase()) }));
|
||||||
|
setTemplatesList(canUseTemplates);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [customerOrderProfile, setCustomerProfile] = useState({});
|
||||||
|
const getCustomerProfile = async (colisn) => {
|
||||||
|
const { result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn });
|
||||||
|
const data = result?.[0] || {};
|
||||||
|
setCustomerProfile(data);
|
||||||
|
|
||||||
|
if (!isEmpty(data.conversation)) {
|
||||||
|
setConversationsList((pre) => [...data.conversations, ...pre]);
|
||||||
|
setCurrentConversation(data.conversation[0]);
|
||||||
|
const thisCMapped = data.conversation.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
||||||
|
setActiveConversations((pre) => ({ ...pre, ...thisCMapped }));
|
||||||
|
setMessages([]); // todo: 获取当前会话的历史消息
|
||||||
|
} else {
|
||||||
|
// reset chat window
|
||||||
|
setMessages([]);
|
||||||
|
if (isEmpty(data.contact?.[0]?.whatsapp_phone_number)) {
|
||||||
|
setCurrentConversation({ sn: '', customer_name: '', coli_sn: '' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 加入新会话
|
||||||
|
const newChat = {
|
||||||
|
'sn': uuid(),
|
||||||
|
// 'opi_sn': 354,
|
||||||
|
'coli_sn': colisn,
|
||||||
|
'whatsapp_phone_number': data.contact[0].whatsapp_phone_number,
|
||||||
|
"last_received_time": '',
|
||||||
|
"last_send_time": '',
|
||||||
|
'unread_msg_count': 0,
|
||||||
|
'whatsapp_name': data.contact[0].name,
|
||||||
|
'customer_name': data.contact[0].name,
|
||||||
|
};
|
||||||
|
setConversationsList((pre) => [...pre, newChat]);
|
||||||
|
setActiveConversations((pre) => ({ ...pre, [`${newChat.sn}`]: [] }));
|
||||||
|
setCurrentConversation(pick(newChat, ['sn', 'coli_sn', 'whatsapp_phone_number', 'whatsapp_name', 'customer_name']));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const switchConversation = (cc) => {
|
||||||
|
setCurrentID(`${cc.sn}`);
|
||||||
|
setCurrentConversation({...cc, id: cc.sn, customer_name: cc.whatsapp_name.trim()});
|
||||||
|
|
||||||
|
if (isEmpty(cc.coli_sn) || cc.coli_sn === '0') {
|
||||||
|
setCustomerProfile({});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get customer profile when switching conversation
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('currentConversation', currentConversation);
|
||||||
|
setCurrentID(currentConversation.sn);
|
||||||
|
setMessages([...(activeConversations[currentConversation.sn] || [])]);
|
||||||
|
return () => {};
|
||||||
|
}, [currentConversation]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *****************************************************************************************************
|
||||||
|
* websocket --------------------------------------------------------------------------------------------
|
||||||
|
* *****************************************************************************************************
|
||||||
|
*/
|
||||||
|
const addError = (reason) => {
|
||||||
|
setErrors((prevErrors) => [...prevErrors, { reason }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addMessageToConversations = (targetId, message) => {
|
||||||
|
setActiveConversations((prevList) => ({
|
||||||
|
...prevList,
|
||||||
|
[targetId]: [...(prevList[targetId] || []), message],
|
||||||
|
}));
|
||||||
|
// console.log('activeConversations', activeConversations);
|
||||||
|
if (targetId !== currentID) {
|
||||||
|
setConversationsList((prevList) => {
|
||||||
|
return prevList.map((ele) => {
|
||||||
|
if (ele.sn === targetId) {
|
||||||
|
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(messages, 'messages');
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [messages])
|
||||||
|
|
||||||
|
|
||||||
|
const addMessage = (message) => {
|
||||||
|
addMessageToConversations(message.conversationid, message);
|
||||||
|
if (message.conversationid === currentID) {
|
||||||
|
setMessages((prevMessages) => [...prevMessages, message]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateMessage = (message) => {
|
||||||
|
let targetMsgs;
|
||||||
|
setMessages((prevMessages) => {
|
||||||
|
targetMsgs = prevMessages.map(ele => {
|
||||||
|
if (ele.id === ele.actionId && ele.actionId === message.actionId) {
|
||||||
|
return {...ele, id: message.id, status: message.status, dateString: message.dateString};
|
||||||
|
}
|
||||||
|
else if (ele.id === message.id) {
|
||||||
|
return {...ele, id: message.id, status: message.status, dateString: message.dateString};
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
return targetMsgs;
|
||||||
|
});
|
||||||
|
// 更新会话中的消息
|
||||||
|
const targetId = message.conversationid; // currentConversationRef.current.sn;
|
||||||
|
setActiveConversations((prevList) => ({
|
||||||
|
...prevList,
|
||||||
|
[targetId]: targetMsgs,
|
||||||
|
}));
|
||||||
|
// 更新列表的时间
|
||||||
|
setConversationsList((prevList) => {
|
||||||
|
return prevList.map((ele) => {
|
||||||
|
if (ele.sn === targetId) {
|
||||||
|
return { ...ele, new_msgs: ele.new_msgs + 1, last_received_time: message.date };
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMessage = (data) => {
|
||||||
|
console.log('handleMessage------------------', );
|
||||||
|
/**
|
||||||
|
* ! event handlers in JavaScript capture the environment (including variables) at the time they are defined, not when they are executed.
|
||||||
|
*/
|
||||||
|
const { errcode, errmsg, result } = data;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let resultType = result?.action || result.type;
|
||||||
|
if (errcode !== 0) {
|
||||||
|
// addError('Error Connecting to Server');
|
||||||
|
resultType = 'error';
|
||||||
|
}
|
||||||
|
console.log(resultType, 'result.type');
|
||||||
|
const msgObj = receivedMsgTypeMapped[resultType].getMsg(result);
|
||||||
|
const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj);
|
||||||
|
const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj);
|
||||||
|
console.log('msgRender msgUpdate', msgRender, msgUpdate);
|
||||||
|
if ( ['whatsapp.message.updated', 'message', 'error'].includes(resultType)) {
|
||||||
|
updateMessage(msgUpdate);
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
if ( ! isEmpty(msgRender)) {
|
||||||
|
addMessage(msgRender);
|
||||||
|
}
|
||||||
|
console.log('handleMessage*******************', );
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendMessage = (msgObj) => {
|
||||||
|
const contentToSend = sentMsgTypeMapped[msgObj.type].contentToSend(msgObj);
|
||||||
|
realtimeAPI.sendMessage({ ...contentToSend, opi_sn: userId });
|
||||||
|
const contentToRender = sentMsgTypeMapped[msgObj.type].contentToRender(msgObj);
|
||||||
|
console.log(contentToRender, 'contentToRender sendMessage------------------');
|
||||||
|
addMessage(contentToRender);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
errors,
|
||||||
|
messages,
|
||||||
|
conversationsList,
|
||||||
|
currentConversation,
|
||||||
|
sendMessage,
|
||||||
|
getConversationsList,
|
||||||
|
switchConversation,
|
||||||
|
templates: templatesList, // setTemplates, getTemplates,
|
||||||
|
customerOrderProfile, getCustomerProfile,
|
||||||
|
poseConversationItemClose
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// test:
|
||||||
|
const testConversations = [
|
||||||
|
{
|
||||||
|
'sn': 3001,
|
||||||
|
'opi_sn': 354,
|
||||||
|
'coli_sn': 0,
|
||||||
|
'whatsapp_phone_number': '+8618777396951',
|
||||||
|
"last_received_time": new Date().toDateString(),
|
||||||
|
"last_send_time": new Date().toDateString(),
|
||||||
|
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
||||||
|
'whatsapp_name': 'LiaoYijun',
|
||||||
|
'customer_name': 'LiaoYijun',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'sn': 3002,
|
||||||
|
'opi_sn': 354,
|
||||||
|
'coli_sn': 0,
|
||||||
|
'whatsapp_phone_number': '+8613317835586',
|
||||||
|
"last_received_time": new Date().toDateString(),
|
||||||
|
"last_send_time": new Date().toDateString(),
|
||||||
|
'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
||||||
|
'whatsapp_name': 'QinQianSheng',
|
||||||
|
'customer_name': 'QinQianSheng',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// 'sn': 3003,
|
||||||
|
// 'opi_sn': 354,
|
||||||
|
// 'coli_sn': 240129003,
|
||||||
|
// 'whatsapp_phone_number': '+8618777396951',
|
||||||
|
// "last_received_time": new Date().toDateString(),
|
||||||
|
// "last_send_time": new Date().toDateString(),
|
||||||
|
// 'unread_msg_count': Math.floor(Math.random() * (100 - 2 + 1) + 2),
|
||||||
|
// 'whatsapp_name': 'LeiYuanTing',
|
||||||
|
// },
|
||||||
|
];
|
@ -0,0 +1,99 @@
|
|||||||
|
import initialState from '@/stores/Conversations/initialState';
|
||||||
|
|
||||||
|
const NAME_SPACE = 'CONVERSATION/';
|
||||||
|
|
||||||
|
const ConversationReducer = (state = initialState, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case NAME_SPACE + 'INIT_WEBSOCKET':
|
||||||
|
return { ...state, websocket: action.payload };
|
||||||
|
|
||||||
|
case NAME_SPACE + 'SET_CONVERSATION_LIST':
|
||||||
|
return { ...state, conversationsList: action.payload };
|
||||||
|
case NAME_SPACE + 'ADD_CONVERSATIONS':
|
||||||
|
return { ...state, conversationsList: [...action.payload, ...state.conversationsList] };
|
||||||
|
|
||||||
|
case NAME_SPACE + 'SET_TEMPLATE_LIST':
|
||||||
|
return { ...state, templates: action.payload };
|
||||||
|
|
||||||
|
case NAME_SPACE + 'SET_CUSTOMER_ORDER_PROFILE':
|
||||||
|
return { ...state, customerOrderProfile: action.payload };
|
||||||
|
|
||||||
|
case NAME_SPACE + 'SET_CURRENT_CONVERSATION': {
|
||||||
|
// 清空未读
|
||||||
|
const { conversationsList } = state;
|
||||||
|
const targetId = action.payload.sn;
|
||||||
|
const newConversationList = conversationsList.map((ele) => {
|
||||||
|
if (ele.sn === targetId) {
|
||||||
|
return { ...ele, unread_msg_count: 0 };
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...state, currentConversation: action.payload, conversationsList: newConversationList };
|
||||||
|
}
|
||||||
|
case NAME_SPACE + 'SET_ACTIVE_CONVERSATIONS': {
|
||||||
|
const { activeConversations } = state;
|
||||||
|
return { ...state, activeConversations: { ...activeConversations, ...action.payload } };
|
||||||
|
}
|
||||||
|
case NAME_SPACE + 'UPDATE_SENT_MESSAGE_ITEM': {
|
||||||
|
console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------');
|
||||||
|
// 更新会话中的消息
|
||||||
|
const { activeConversations, conversationsList } = state;
|
||||||
|
const message = action.payload;
|
||||||
|
const targetId = message.conversationid;
|
||||||
|
const targetMsgs = (activeConversations[targetId] || []).map((ele) => {
|
||||||
|
if (ele.id === ele.actionId && ele.actionId === message.actionId) {
|
||||||
|
return { ...ele, id: message.id, status: message.status, dateString: message.dateString };
|
||||||
|
} else if (ele.id === message.id) {
|
||||||
|
return { ...ele, id: message.id, status: message.status, dateString: message.dateString };
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新列表的时间
|
||||||
|
const newConversationList = conversationsList.map((ele) => {
|
||||||
|
if (ele.sn === targetId && message.type !== 'error') {
|
||||||
|
return { ...ele, last_received_time: message.date };
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
activeConversations: { ...state.activeConversations, [targetId]: targetMsgs },
|
||||||
|
conversationsList: newConversationList,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case NAME_SPACE + 'SENT_NEW_MESSAGE':
|
||||||
|
case NAME_SPACE + 'RECEIVED_NEW_MESSAGE': {
|
||||||
|
const { activeConversations, conversationsList, currentConversation } = state;
|
||||||
|
const { targetId, message } = action.payload;
|
||||||
|
const targetMsgs = activeConversations[targetId] || [];
|
||||||
|
console.log(activeConversations, targetId, 'sent sent sent');
|
||||||
|
const newConversationList = conversationsList.map((ele) => {
|
||||||
|
if (ele.sn === targetId) {
|
||||||
|
return {
|
||||||
|
...ele,
|
||||||
|
last_received_time: message.date,
|
||||||
|
unread_msg_count: ele.sn === currentConversation.sn ? ele.unread_msg_count + 1 : ele.unread_msg_count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return ele;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
activeConversations: { ...activeConversations, [targetId]: [...targetMsgs, message] },
|
||||||
|
conversationsList: newConversationList,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case NAME_SPACE + 'ADD_ERROR': {
|
||||||
|
console.log('add error', state.errors, action.payload);
|
||||||
|
const prelist = state.errors || [];
|
||||||
|
return { ...state, errors: [...prelist, action.payload] };
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// throw new Error(`Unknown action: ${action.type}`);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export default ConversationReducer;
|
@ -0,0 +1,13 @@
|
|||||||
|
const initialState = {
|
||||||
|
websocket: null,
|
||||||
|
errors: [], // 错误信息
|
||||||
|
|
||||||
|
conversationsList: [], // 对话列表
|
||||||
|
templates: [],
|
||||||
|
customerOrderProfile: {},
|
||||||
|
|
||||||
|
activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] }
|
||||||
|
currentConversation: {}, // 当前对话
|
||||||
|
|
||||||
|
};
|
||||||
|
export default initialState;
|
@ -1,30 +1,97 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext, useReducer, useEffect } from 'react';
|
||||||
import { ConversationContext, useConversations, } from '@/stores/Conversations/ConversationContext';
|
import { ConversationContext, ConversationStateContext, ConversationDispatchContext } from '@/stores/Conversations/ConversationContext';
|
||||||
|
import ConversationReducer from '@/stores/Conversations/ConversationReducer';
|
||||||
|
import {
|
||||||
|
initWebsocket,
|
||||||
|
addError,
|
||||||
|
fetchConversationsList,
|
||||||
|
fetchTemplates,
|
||||||
|
receivedConversationList,
|
||||||
|
receivedTemplates,
|
||||||
|
setActiveConversations,
|
||||||
|
updateMessageItem,
|
||||||
|
receivedNewMessage,
|
||||||
|
} from '@/stores/Conversations/ConversationActions';
|
||||||
|
import initialState from '@/stores/Conversations/initialState';
|
||||||
|
|
||||||
import { AuthContext } from '@/stores/AuthContext';
|
import { AuthContext } from '@/stores/AuthContext';
|
||||||
|
|
||||||
import { RealTimeAPI } from '@/lib/realTimeAPI';
|
import { RealTimeAPI } from '@/lib/realTimeAPI';
|
||||||
|
import { receivedMsgTypeMapped } from '@/lib/msgUtils';
|
||||||
|
import { isEmpty } from '@/utils/utils';
|
||||||
|
|
||||||
// const WS_URL = 'ws://202.103.68.144:8888/whatever/';
|
// const WS_URL = 'ws://202.103.68.144:8888/whatever/';
|
||||||
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
|
// const WS_URL = 'ws://120.79.9.217:10022/whatever/';
|
||||||
const WS_URL = 'wss://p9axztuwd7x8a7.mycht.cn/whatsapp_callback'; // prod:
|
const WS_URL = 'wss://p9axztuwd7x8a7.mycht.cn/whatsapp_callback'; // prod:
|
||||||
|
|
||||||
export const ConversationProvider = ({ children, loginUser, realtimeAPI }) => {
|
const ConversationProvider = ({ children }) => {
|
||||||
|
const { loginUser } = useContext(AuthContext);
|
||||||
|
const { userId } = loginUser;
|
||||||
|
console.log('====', loginUser);
|
||||||
|
|
||||||
const conversations = useConversations({loginUser, realtimeAPI});
|
const realtimeAPI = new RealTimeAPI({ url: `${WS_URL}?opisn=${userId || ''}&_spam=${Date.now().toString()}`, protocol: 'WhatsApp' });
|
||||||
return <ConversationContext.Provider value={conversations}>{children}</ConversationContext.Provider>;
|
const [state, dispatch] = useReducer(ConversationReducer, { ...initialState, websocket: null });
|
||||||
};
|
|
||||||
|
|
||||||
// export default ConversationProvider;
|
console.log('ConversationProvider', state, dispatch);
|
||||||
|
|
||||||
const AuthAndConversationProvider = ({ children }) => {
|
useEffect(() => {
|
||||||
const { loginUser } = useContext(AuthContext);
|
console.log('invoke provider');
|
||||||
const {userId} = loginUser;
|
|
||||||
const realtimeAPI = new RealTimeAPI({ url: `${WS_URL}?opisn=${userId || ''}&_spam=${Date.now().toString()}`, protocol: 'WhatsApp' });
|
realtimeAPI.onError(() => dispatch(addError('Error')));
|
||||||
|
realtimeAPI.onMessage(handleMessage);
|
||||||
|
realtimeAPI.onCompletion(() => dispatch(addError('Connection broken')));
|
||||||
|
|
||||||
|
dispatch(initWebsocket(realtimeAPI));
|
||||||
|
return () => {
|
||||||
|
realtimeAPI.disconnect();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchConversationsList(userId).then((data) => {
|
||||||
|
console.log(data, 'llllllllllllllllllllllll');
|
||||||
|
const dataMapped = data.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {});
|
||||||
|
dispatch(receivedConversationList(data));
|
||||||
|
dispatch(setActiveConversations(dataMapped));
|
||||||
|
}); // todo: 和刷新订单会话页面有冲突
|
||||||
|
|
||||||
|
fetchTemplates().then((data) => dispatch(receivedTemplates(data)));
|
||||||
|
|
||||||
|
return () => {};
|
||||||
|
}, []);
|
||||||
|
const handleMessage = (data) => {
|
||||||
|
console.log('handleMessage------------------');
|
||||||
|
console.log(data);
|
||||||
|
const { errcode, errmsg, result } = data;
|
||||||
|
|
||||||
return (
|
if (!result) {
|
||||||
<ConversationProvider loginUser={loginUser} realtimeAPI={realtimeAPI} >
|
return false;
|
||||||
{children}
|
}
|
||||||
</ConversationProvider>
|
let resultType = result?.action || result.type;
|
||||||
);
|
if (errcode !== 0) {
|
||||||
|
// addError('Error Connecting to Server');
|
||||||
|
resultType = 'error';
|
||||||
|
}
|
||||||
|
console.log(resultType, 'result.type');
|
||||||
|
const msgObj = receivedMsgTypeMapped[resultType].getMsg(result);
|
||||||
|
const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj);
|
||||||
|
const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj);
|
||||||
|
console.log('msgRender msgUpdate', msgRender, msgUpdate);
|
||||||
|
if (['whatsapp.message.updated', 'message', 'error'].includes(resultType)) {
|
||||||
|
dispatch(updateMessageItem(msgUpdate));
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
|
if (!isEmpty(msgRender)) {
|
||||||
|
dispatch(receivedNewMessage(msgRender.conversationid, msgRender));
|
||||||
|
}
|
||||||
|
console.log('handleMessage*******************');
|
||||||
|
};
|
||||||
|
return <ConversationContext.Provider value={{ ...state, dispatch }}>{children}</ConversationContext.Provider>;
|
||||||
|
// return (
|
||||||
|
// <ConversationDispatchContext.Provider value={dispatch}>
|
||||||
|
// <ConversationStateContext.Provider value={{...state}}>{children}</ConversationStateContext.Provider>
|
||||||
|
// </ConversationDispatchContext.Provider>
|
||||||
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AuthAndConversationProvider;
|
export default ConversationProvider;
|
||||||
|
Loading…
Reference in New Issue