import React, { createContext, useContext, useEffect, useState } from 'react'; import { io, Socket } from 'socket.io-client'; import { useSelector } from 'react-redux'; import { RootState } from '../store'; interface SocketContextType { socket: Socket | null; isConnected: boolean; } const SocketContext = createContext({ socket: null, isConnected: false }); export const useSocket = () => useContext(SocketContext); export const SocketProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [socket, setSocket] = useState(null); const [isConnected, setIsConnected] = useState(false); const { user: currentUser } = useSelector((state: RootState) => state.auth); useEffect(() => { let socketUrl = (import.meta as any).env.VITE_API_URL || 'http://localhost:5000'; // If URL ends with /api, strip it as Socket.io usually connects to the root if (socketUrl.endsWith('/api')) { socketUrl = socketUrl.replace(/\/api$/, ''); } const newSocket = io(socketUrl, { withCredentials: true }); newSocket.on('connect', () => { console.log('Socket connected:', newSocket.id); setIsConnected(true); }); newSocket.on('disconnect', () => { console.log('Socket disconnected'); setIsConnected(false); }); setSocket(newSocket); return () => { newSocket.close(); }; }, []); // Join personal room for notifications useEffect(() => { if (socket && isConnected && currentUser?.id) { socket.emit('join_room', `user_${currentUser.id}`); console.log(`Joined private notification room: user_${currentUser.id}`); return () => { socket.emit('leave_room', `user_${currentUser.id}`); }; } }, [socket, isConnected, currentUser?.id]); return ( {children} ); };