import { useState, useEffect } from 'react'; import { connectSocket, getSocket } from '../services/socket'; import { matchesAPI } from '../services/api'; /** * Custom hook for Match Chat functionality (1:1 private chat) * Extracts Socket.IO logic and chat state management from MatchChatPage * * @param {object} match - Match object with id and partner info * @param {number} userId - Current user ID * @param {string} slug - Match slug for API calls * @returns {object} Chat state and handlers * * @example * const { * messages, * isConnected, * sendMessage, * newMessage, * setNewMessage * } = useMatchChat(match, user.id, slug); */ const useMatchChat = (match, userId, slug) => { // Chat state const [messages, setMessages] = useState([]); const [newMessage, setNewMessage] = useState(''); const [isConnected, setIsConnected] = useState(false); // Load message history from API useEffect(() => { const loadMessages = async () => { if (!match || !slug) return; try { const result = await matchesAPI.getMatchMessages(slug); setMessages(result.data || []); } catch (error) { console.error('Failed to load messages:', error); } }; loadMessages(); }, [match, slug]); // Socket.IO connection and event listeners useEffect(() => { // Wait for match to be loaded if (!match) return; // Connect to Socket.IO const socket = connectSocket(); if (!socket) { console.error('Failed to connect to socket'); return; } // Helper to join match room const joinMatchRoom = () => { setIsConnected(true); socket.emit('join_match_room', { matchId: match.id }); console.log(`Joined match room ${match.id}`); }; // Socket event listeners socket.on('connect', joinMatchRoom); socket.on('disconnect', (reason) => { setIsConnected(false); console.log('🔌 Match chat disconnected:', reason); }); // Handle reconnection socket.on('reconnect', (attemptNumber) => { console.log('🔄 Match chat reconnected after', attemptNumber, 'attempts'); }); socket.on('reconnect_attempt', (attemptNumber) => { console.log('🔄 Match chat reconnection attempt', attemptNumber); }); // Receive messages socket.on('match_message', (message) => { setMessages((prev) => [...prev, message]); }); // Join immediately if already connected if (socket.connected) { joinMatchRoom(); } // Cleanup return () => { socket.off('connect', joinMatchRoom); socket.off('disconnect'); socket.off('reconnect'); socket.off('reconnect_attempt'); socket.off('match_message'); }; }, [match, userId]); /** * Send a message to the match chat */ const sendMessage = (e) => { e.preventDefault(); if (!newMessage.trim() || !match) return; const socket = getSocket(); if (!socket || !socket.connected) { alert('Not connected to chat server'); return; } // Send message via Socket.IO using numeric match ID socket.emit('send_match_message', { matchId: match.id, content: newMessage, }); setNewMessage(''); }; return { // State messages, newMessage, setNewMessage, isConnected, // Actions sendMessage }; }; export default useMatchChat;