feature/IO-3000-Migrate-MSG-to-Sockets - Progress Checkpoint
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -12,8 +12,6 @@ export default function ChatConversationComponent({ subState, conversation, mess
|
||||
if (loading) return <LoadingSkeleton />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
console.dir(conversation);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="chat-conversation"
|
||||
|
||||
@@ -5,18 +5,15 @@ import { selectSelectedConversation } from "../../redux/messaging/messaging.sele
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import ChatConversationComponent from "./chat-conversation.component";
|
||||
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
|
||||
import { updateUnreadCount } from "../../redux/messaging/messaging.actions.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
updateUnreadCounts: (data) => dispatch(updateUnreadCount(data.conversationId, data.unreadcnt))
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function ChatConversationContainer({ bodyshop, selectedConversation, updateUnreadCounts }) {
|
||||
export function ChatConversationContainer({ bodyshop, selectedConversation }) {
|
||||
const { socket } = useContext(SocketContext);
|
||||
const [conversationDetails, setConversationDetails] = useState({});
|
||||
const [messages, setMessages] = useState([]);
|
||||
@@ -40,10 +37,6 @@ export function ChatConversationContainer({ bodyshop, selectedConversation, upda
|
||||
setMessages((prevMessages) => [...prevMessages, message]);
|
||||
});
|
||||
|
||||
socket.on("unread-count-updated", (data) => {
|
||||
updateUnreadCounts(data);
|
||||
});
|
||||
|
||||
socket.on("conversation-list-updated", (data) => {
|
||||
setConversationDetails(data.conversation);
|
||||
setMessages(data.messages);
|
||||
@@ -53,11 +46,10 @@ export function ChatConversationContainer({ bodyshop, selectedConversation, upda
|
||||
socket.emit("leave-conversation", selectedConversation);
|
||||
socket.off("conversation-details");
|
||||
socket.off("new-message");
|
||||
socket.off("unread-count-updated");
|
||||
socket.off("conversation-list-updated");
|
||||
};
|
||||
}
|
||||
}, [socket, selectedConversation, updateUnreadCounts]);
|
||||
}, [socket, selectedConversation]);
|
||||
|
||||
// Mark messages as read
|
||||
const handleMarkConversationAsRead = async () => {
|
||||
|
||||
@@ -47,14 +47,12 @@ const useSocket = (bodyshop) => {
|
||||
};
|
||||
|
||||
const handleConnect = () => {
|
||||
console.log("Socket connected:", socketInstance.id);
|
||||
socketInstance.emit("join-bodyshop-room", bodyshop.id);
|
||||
setClientId(socketInstance.id);
|
||||
store.dispatch(setWssStatus("connected"));
|
||||
};
|
||||
|
||||
const handleReconnect = (attempt) => {
|
||||
console.log(`Socket reconnected after ${attempt} attempts`);
|
||||
store.dispatch(setWssStatus("connected"));
|
||||
};
|
||||
|
||||
@@ -64,7 +62,6 @@ const useSocket = (bodyshop) => {
|
||||
};
|
||||
|
||||
const handleDisconnect = () => {
|
||||
console.log("Socket disconnected");
|
||||
store.dispatch(setWssStatus("disconnected"));
|
||||
};
|
||||
|
||||
@@ -81,13 +78,8 @@ const useSocket = (bodyshop) => {
|
||||
dispatch({ type: "ADD_MESSAGE", payload: data.message });
|
||||
};
|
||||
|
||||
// const handleReadUpdated = ({ conversationId }) => {
|
||||
// dispatch({ type: "UPDATE_UNREAD_COUNT", payload: conversationId });
|
||||
// };
|
||||
|
||||
socketInstance.on("messaging-list", handleMessagingList);
|
||||
socketInstance.on("new-message", handleNewMessage);
|
||||
// socketInstance.on("mark-as-read", handleReadUpdated);
|
||||
socketInstance.on("connect", handleConnect);
|
||||
socketInstance.on("reconnect", handleReconnect);
|
||||
socketInstance.on("connect_error", handleConnectionError);
|
||||
|
||||
@@ -6,8 +6,10 @@ const INITIAL_STATE = {
|
||||
isSending: false,
|
||||
error: null,
|
||||
message: null,
|
||||
conversations: [], // Holds the list of conversations
|
||||
messages: [], // Holds the list of messages for the selected conversation
|
||||
conversations: {
|
||||
conversations: []
|
||||
},
|
||||
messages: [],
|
||||
unreadcnt: 0,
|
||||
searchingForConversation: false
|
||||
};
|
||||
@@ -72,34 +74,19 @@ const messagingReducer = (state = INITIAL_STATE, action) => {
|
||||
};
|
||||
|
||||
case MessagingActionTypes.ADD_CONVERSATION:
|
||||
return {
|
||||
...state,
|
||||
conversations: [...state.conversations, action.payload]
|
||||
};
|
||||
|
||||
case MessagingActionTypes.UPDATE_UNREAD_COUNT:
|
||||
return {
|
||||
...state,
|
||||
conversations: {
|
||||
...state.conversations,
|
||||
conversations: state.conversations.conversations.map((conversation) =>
|
||||
conversation.id === action.payload.conversationId
|
||||
? { ...conversation, unreadcnt: action.payload.unreadcnt } // Update unread count to the value in the payload
|
||||
: conversation
|
||||
)
|
||||
},
|
||||
unreadcnt: Math.max(
|
||||
state.conversations.conversations.reduce(
|
||||
(total, conversation) =>
|
||||
conversation.id === action.payload.conversationId
|
||||
? total + action.payload.unreadcnt
|
||||
: total + conversation.unreadcnt,
|
||||
0
|
||||
),
|
||||
0
|
||||
) // Recalculate the global unreadcnt based on all conversations
|
||||
conversations: [
|
||||
...(state.conversations.conversations || []),
|
||||
{
|
||||
...action.payload, // Ensure all fields from payload are included
|
||||
messages_aggregate: action.payload.messages_aggregate || { aggregate: { count: 0 } }
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,21 @@ mutation RECEIVE_MESSAGE($msg: [messages_insert_input!]!) {
|
||||
updated_at
|
||||
unreadcnt
|
||||
phone_num
|
||||
label
|
||||
job_conversations {
|
||||
job {
|
||||
id
|
||||
ro_number
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
}
|
||||
}
|
||||
messages_aggregate {
|
||||
aggregate {
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
conversationid
|
||||
created_at
|
||||
|
||||
@@ -63,18 +63,28 @@ exports.receive = async (req, res) => {
|
||||
// Insert new conversation and message
|
||||
const insertresp = await client.request(queries.RECEIVE_MESSAGE, { msg: newMessage });
|
||||
|
||||
const createdConversation = insertresp.insert_conversations.returning[0];
|
||||
const message = insertresp.insert_messages.returning[0];
|
||||
// Safely access conversation and message
|
||||
const createdConversation = insertresp?.insert_messages?.returning?.[0]?.conversation || null;
|
||||
const message = insertresp?.insert_messages?.returning?.[0] || {
|
||||
text: "",
|
||||
image: false,
|
||||
image_path: []
|
||||
};
|
||||
|
||||
if (!createdConversation) {
|
||||
throw new Error("Conversation data is missing from the response.");
|
||||
}
|
||||
|
||||
// Emit new conversation event
|
||||
ioRedis.to(getBodyshopRoom(response.bodyshops[0].id)).emit("new-conversation", {
|
||||
conversation: createdConversation,
|
||||
message: {
|
||||
...message,
|
||||
text: message.text || "",
|
||||
image: message.image || false,
|
||||
image_path: message.image_path || []
|
||||
}
|
||||
conversation: {
|
||||
...createdConversation,
|
||||
messages_aggregate: {
|
||||
aggregate: {
|
||||
count: 1 // Adjust dynamically based on your logic or default to 0
|
||||
}
|
||||
}
|
||||
},
|
||||
message
|
||||
});
|
||||
|
||||
logger.log("sms-inbound-success", "DEBUG", "api", null, {
|
||||
@@ -99,6 +109,7 @@ exports.receive = async (req, res) => {
|
||||
}
|
||||
} else if (response.bodyshops[0].conversations.length === 1) {
|
||||
// Add to the existing conversation
|
||||
// conversation UPDATED
|
||||
newMessage.conversationid = response.bodyshops[0].conversations[0].id;
|
||||
} else {
|
||||
// Duplicate phone error
|
||||
|
||||
@@ -140,11 +140,6 @@ const redisSocketEvents = ({
|
||||
};
|
||||
// Messaging Events
|
||||
const registerMessagingEvents = (socket) => {
|
||||
const broadcastNewMessage = async (message) => {
|
||||
const room = `conversation-${message.conversationId}`;
|
||||
io.to(room).emit("new-message", message);
|
||||
};
|
||||
|
||||
const openMessaging = async (bodyshopUUID) => {
|
||||
try {
|
||||
const conversations = await client.request(GET_CONVERSATIONS, { bodyshopId: bodyshopUUID });
|
||||
@@ -282,6 +277,19 @@ const redisSocketEvents = ({
|
||||
}
|
||||
};
|
||||
|
||||
const leaveConversation = (conversationId) => {
|
||||
try {
|
||||
const room = `conversation-${conversationId}`;
|
||||
socket.leave(room);
|
||||
|
||||
// Optionally notify the client
|
||||
socket.emit("conversation-left", { conversationId });
|
||||
} catch (error) {
|
||||
socket.emit("error", { message: "Failed to leave conversation" });
|
||||
}
|
||||
};
|
||||
|
||||
socket.on("leave-conversation", leaveConversation);
|
||||
socket.on("send-message", sendMessage);
|
||||
socket.on("mark-as-read", markAsRead);
|
||||
socket.on("join-conversation", joinConversation);
|
||||
|
||||
Reference in New Issue
Block a user