Files
spotlightcam/frontend/src/hooks/useMatchChat.js

135 lines
3.3 KiB
JavaScript
Raw Normal View History

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;