import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import Layout from '../components/layout/Layout'; import { useAuth } from '../contexts/AuthContext'; import { matchesAPI } from '../services/api'; import { MessageCircle, Check, X, Loader2, Users, Calendar, MapPin } from 'lucide-react'; import { connectSocket, disconnectSocket, getSocket } from '../services/socket'; const MatchesPage = () => { const { user } = useAuth(); const navigate = useNavigate(); const [matches, setMatches] = useState([]); const [loading, setLoading] = useState(true); const [filter, setFilter] = useState('all'); // 'all', 'pending', 'accepted' const [processingMatchId, setProcessingMatchId] = useState(null); useEffect(() => { loadMatches(); // Connect to socket for real-time updates const token = localStorage.getItem('token'); if (token && user) { connectSocket(token, user.id); const socket = getSocket(); if (socket) { // Listen for match notifications socket.on('match_request_received', handleMatchRequestReceived); socket.on('match_accepted', handleMatchAccepted); socket.on('match_cancelled', handleMatchCancelled); } } return () => { const socket = getSocket(); if (socket) { socket.off('match_request_received', handleMatchRequestReceived); socket.off('match_accepted', handleMatchAccepted); socket.off('match_cancelled', handleMatchCancelled); } disconnectSocket(); }; }, [user]); const loadMatches = async () => { try { setLoading(true); const result = await matchesAPI.getMatches(); setMatches(result.data || []); } catch (error) { console.error('Failed to load matches:', error); } finally { setLoading(false); } }; const handleMatchRequestReceived = (data) => { // Reload matches to show new request loadMatches(); }; const handleMatchAccepted = (data) => { // Reload matches to update status loadMatches(); }; const handleMatchCancelled = (data) => { // Remove cancelled match from list setMatches(prev => prev.filter(m => m.id !== data.matchId)); }; const handleAccept = async (matchId) => { try { setProcessingMatchId(matchId); await matchesAPI.acceptMatch(matchId); // Reload matches await loadMatches(); // Show success message alert('Match accepted! You can now chat with your partner.'); } catch (error) { console.error('Failed to accept match:', error); alert('Failed to accept match. Please try again.'); } finally { setProcessingMatchId(null); } }; const handleReject = async (matchId) => { if (!confirm('Are you sure you want to reject this match request?')) { return; } try { setProcessingMatchId(matchId); await matchesAPI.deleteMatch(matchId); // Remove from list setMatches(prev => prev.filter(m => m.id !== matchId)); } catch (error) { console.error('Failed to reject match:', error); alert('Failed to reject match. Please try again.'); } finally { setProcessingMatchId(null); } }; const handleOpenChat = (match) => { if (match.status === 'accepted' && match.roomId) { navigate(`/matches/${match.id}/chat`); } }; // Filter matches based on selected filter const filteredMatches = matches.filter(match => { if (filter === 'all') return true; return match.status === filter; }); // Separate pending incoming matches (where user is recipient) const pendingIncoming = filteredMatches.filter(m => m.status === 'pending' && !m.isInitiator); const otherMatches = filteredMatches.filter(m => !(m.status === 'pending' && !m.isInitiator)); return (

Match Requests

Manage your dance partner connections

{/* Filter Tabs */}
{loading ? (
) : ( <> {/* Pending Incoming Requests Section */} {pendingIncoming.length > 0 && (

Incoming Requests

{pendingIncoming.map(match => ( ))}
)} {/* Other Matches */} {otherMatches.length > 0 && (

{pendingIncoming.length > 0 ? 'Other Matches' : 'Your Matches'}

{otherMatches.map(match => ( ))}
)} {/* Empty State */} {filteredMatches.length === 0 && (

No matches found

{filter === 'all' ? 'You have no match requests yet. Connect with other dancers at events!' : `You have no ${filter} matches.`}

)} )}
); }; const MatchCard = ({ match, onAccept, onReject, onOpenChat, processing }) => { const isIncoming = !match.isInitiator && match.status === 'pending'; const isOutgoing = match.isInitiator && match.status === 'pending'; const isAccepted = match.status === 'accepted'; return (
{match.partner.username}

{match.partner.firstName && match.partner.lastName ? `${match.partner.firstName} ${match.partner.lastName}` : match.partner.username}

@{match.partner.username}

{match.event.name}
{match.event.location}
{isIncoming && ( Incoming Request )} {isOutgoing && ( Sent Request )} {isAccepted && ( Active Match )}
{isIncoming && ( <> )} {isOutgoing && ( )} {isAccepted && ( )}
); }; export default MatchesPage;