import React, { createContext, useContext, useEffect, useState } from 'react'; import { io } from 'socket.io-client'; import { useAuth } from './AuthContext'; const SocketContext = createContext(); export function useSocket() { const context = useContext(SocketContext); if (!context) { throw new Error('useSocket must be used within SocketProvider'); } return context; } export function SocketProvider({ children }) { const [socket, setSocket] = useState(null); const [connected, setConnected] = useState(false); const { user, token } = useAuth(); useEffect(() => { // Only connect if user is authenticated if (!user || !token) { console.log('⏳ Waiting for authentication...', { user: !!user, token: !!token }); if (socket) { socket.disconnect(); setSocket(null); setConnected(false); } return; } console.log('🔄 Initializing socket connection...'); // Determine backend URL (strip /api if present since socket.io is at root) let backendUrl = import.meta.env.VITE_API_URL || (import.meta.env.DEV ? 'http://localhost:4000' : window.location.origin); // Remove /api suffix if present backendUrl = backendUrl.replace(/\/api$/, ''); console.log('🌐 Connecting to:', backendUrl); // Create socket connection with JWT authentication const newSocket = io(backendUrl, { auth: { token }, reconnection: true, reconnectionAttempts: 5, reconnectionDelay: 1000 }); newSocket.on('connect', () => { console.log('🔌 Socket connected'); setConnected(true); }); newSocket.on('disconnect', () => { console.log('❌ Socket disconnected'); setConnected(false); }); newSocket.on('connect_error', (error) => { console.error('❌ Socket connection error:', error.message); console.error(' Error details:', error); }); setSocket(newSocket); // Cleanup on unmount return () => { newSocket.disconnect(); }; }, [user, token]); const joinChallenge = (challengeId) => { if (socket && connected) { console.log(`📍 Joining challenge room: ${challengeId}`); socket.emit('join:challenge', challengeId); } else { console.warn(`⚠️ Cannot join challenge ${challengeId} - socket:`, !!socket, 'connected:', connected); } }; const leaveChallenge = (challengeId) => { if (socket && connected) { console.log(`👋 Leaving challenge room: ${challengeId}`); socket.emit('leave:challenge', challengeId); } }; const value = { socket, connected, joinChallenge, leaveChallenge }; return ( {children} ); }