/* eslint-disable @typescript-eslint/no-explicit-any */ import { ChevronLeft, MessageCircle } from "lucide-react"; import { useEffect } from "react"; import MessageInput from "./MessageInput"; import Messages from "./Messages"; import useChatUIStore from "../../stores/Zustant"; import { useChatContext } from "../../providers/ChatProvider"; import { getChatConfig } from "../../Chat.config"; import defaultProfilePicture from "../../assets/pngegg.png"; import Avatar from "../common/Avatar"; const MessageContainer = () => { const { userId } = useChatContext(); const { selectedConversation, setSelectedConversation, setOnlineUsers } = useChatUIStore(); const { socket, isUserOnline } = useChatContext(); const { role } = getChatConfig(); useEffect(() => { if (!socket || !selectedConversation?._id) return; const sendJoinChat = () => { socket.send( JSON.stringify({ event: "joinChat", data: { chatId: selectedConversation._id, userId: userId, role: role, }, }) ); // Bulk-mark all existing unread messages as read when the conversation is opened const unreadIds = selectedConversation.unreadMessageIds ?? []; const lastMsg = selectedConversation.lastMessage; if (unreadIds.length > 0 && lastMsg) { socket.send( JSON.stringify({ event: "messageRead", data: { messageIds: unreadIds, chatId: selectedConversation._id, senderId: lastMsg.senderId, receiverId: userId, // roles are not always available here — backend should infer from chatId if needed }, }) ); } }; if (socket.readyState === WebSocket.OPEN) { // Socket already open — fire immediately sendJoinChat(); } else if (socket.readyState === WebSocket.CONNECTING) { // Socket still connecting — wait for it to open, then fire once socket.addEventListener("open", sendJoinChat, { once: true }); return () => socket.removeEventListener("open", sendJoinChat); } }, [selectedConversation?._id, socket, userId, role]); useEffect(() => { if (!socket) return; const handleMessage = (event: MessageEvent) => { try { const data = JSON.parse(event.data); if (data.event === "getOnlineUsers") { setOnlineUsers(data.payload); // payload should be an array of user IDs } } catch (err) { console.error("Failed to parse WebSocket message", err); } }; socket.addEventListener("message", handleMessage); return () => { socket.removeEventListener("message", handleMessage); }; }, [socket, setOnlineUsers]); // Listen for online users updates const participantDetails = Array.isArray( selectedConversation?.participantDetails ) ? selectedConversation?.participantDetails : [selectedConversation?.participantDetails].filter(Boolean); const participant = participantDetails.find((p: any) => p._id !== userId); // const participant = selectedConversation?.participantDetails?.find( // (p: any) => p._id !== userId // ); const isOnline = isUserOnline(participant?._id || ""); // Cleanup on unmount useEffect(() => { return () => setSelectedConversation(null); }, [setSelectedConversation]); if (!selectedConversation) return ; const isService = selectedConversation.type === "service"; return (
{isService ? ( ) : ( )}
{isService ? selectedConversation.serviceTitle : participant?.name || "Conversation"} {isOnline ? "Online" : "Offline"}
{isService && selectedConversation.bookingId && ( #{selectedConversation.bookingId} )}
{role !== "admin" && }
); }; export default MessageContainer; // EmptyInbox component remains the same interface EmptyInboxProps { title?: string; description?: string; } const EmptyInbox: React.FC = ({ title = "No conversation selected", description = "Pick a conversation from the list to see the thread here.", }) => (

{title}

{description}

);