From 408317b974b1d388be19258101ee831d629201cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Gierwia=C5=82o?= Date: Sun, 23 Nov 2025 22:28:54 +0100 Subject: [PATCH] refactor(frontend): add CONNECTION_STATE and SUGGESTION_TYPE constants - Add CONNECTION_STATE (disconnected, connecting, connected, failed) - Add SUGGESTION_TYPE (toBeRecorded, toRecord) - Update useWebRTC.js to use CONNECTION_STATE - Update MatchChatPage.jsx to use CONNECTION_STATE - Update RecordingTab.jsx to use SUGGESTION_TYPE --- .../components/recordings/RecordingTab.jsx | 10 ++++---- frontend/src/constants/index.js | 8 ++++++- frontend/src/constants/statuses.js | 18 +++++++++++++++ frontend/src/hooks/useWebRTC.js | 23 ++++++++++--------- frontend/src/pages/MatchChatPage.jsx | 23 ++++++++++--------- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/frontend/src/components/recordings/RecordingTab.jsx b/frontend/src/components/recordings/RecordingTab.jsx index 530dc57..171a720 100644 --- a/frontend/src/components/recordings/RecordingTab.jsx +++ b/frontend/src/components/recordings/RecordingTab.jsx @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'; import { Video, VideoOff, Clock, CheckCircle, XCircle, AlertTriangle, RefreshCw } from 'lucide-react'; import { matchingAPI } from '../../services/api'; import Avatar from '../common/Avatar'; -import { SUGGESTION_STATUS } from '../../constants'; +import { SUGGESTION_STATUS, SUGGESTION_TYPE } from '../../constants'; /** * RecordingTab - Main component for managing recording partnerships @@ -199,7 +199,7 @@ const RecordingTab = ({ slug, event, myHeats }) => { handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)} onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)} /> @@ -225,7 +225,7 @@ const RecordingTab = ({ slug, event, myHeats }) => { handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)} onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)} /> @@ -273,8 +273,8 @@ const SuggestionCard = ({ suggestion, type, onAccept, onReject }) => { ? `${heat.division?.abbreviation || '?'} ${heat.competitionType?.abbreviation || '?'} H${heat.heatNumber}` : 'Unknown heat'; - const person = type === 'toBeRecorded' ? recorder : dancer; - const personLabel = type === 'toBeRecorded' ? 'Nagrywa Cie:' : 'Nagrywasz:'; + const person = type === SUGGESTION_TYPE.TO_BE_RECORDED ? recorder : dancer; + const personLabel = type === SUGGESTION_TYPE.TO_BE_RECORDED ? 'Nagrywa Cie:' : 'Nagrywasz:'; // Status badge const getStatusBadge = () => { diff --git a/frontend/src/constants/index.js b/frontend/src/constants/index.js index f50faf3..ffcf2c7 100644 --- a/frontend/src/constants/index.js +++ b/frontend/src/constants/index.js @@ -1 +1,7 @@ -export { MATCH_STATUS, SUGGESTION_STATUS, MATCH_FILTER } from './statuses'; +export { + MATCH_STATUS, + SUGGESTION_STATUS, + MATCH_FILTER, + CONNECTION_STATE, + SUGGESTION_TYPE, +} from './statuses'; diff --git a/frontend/src/constants/statuses.js b/frontend/src/constants/statuses.js index e872123..9b0b46e 100644 --- a/frontend/src/constants/statuses.js +++ b/frontend/src/constants/statuses.js @@ -26,3 +26,21 @@ export const MATCH_FILTER = { PENDING: 'pending', ACCEPTED: 'accepted', }; + +/** + * WebRTC connection states + */ +export const CONNECTION_STATE = { + DISCONNECTED: 'disconnected', + CONNECTING: 'connecting', + CONNECTED: 'connected', + FAILED: 'failed', +}; + +/** + * Recording suggestion types + */ +export const SUGGESTION_TYPE = { + TO_BE_RECORDED: 'toBeRecorded', + TO_RECORD: 'toRecord', +}; diff --git a/frontend/src/hooks/useWebRTC.js b/frontend/src/hooks/useWebRTC.js index 5c25a75..5cc1a69 100644 --- a/frontend/src/hooks/useWebRTC.js +++ b/frontend/src/hooks/useWebRTC.js @@ -1,5 +1,6 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import { getSocket } from '../services/socket'; +import { CONNECTION_STATE } from '../constants'; // WebRTC configuration with STUN and TURN servers for NAT traversal const rtcConfig = { @@ -39,7 +40,7 @@ const CHUNK_SIZE = 16384; * @returns {Object} WebRTC state and control functions */ export const useWebRTC = (matchId, userId) => { - const [connectionState, setConnectionState] = useState('disconnected'); // disconnected, connecting, connected, failed + const [connectionState, setConnectionState] = useState(CONNECTION_STATE.DISCONNECTED); const [transferProgress, setTransferProgress] = useState(0); const [isTransferring, setIsTransferring] = useState(false); const [receivingFile, setReceivingFile] = useState(null); @@ -117,7 +118,7 @@ export const useWebRTC = (matchId, userId) => { console.log('🔄 Connection state:', pc.connectionState); setConnectionState(pc.connectionState); - if (pc.connectionState === 'failed') { + if (pc.connectionState === CONNECTION_STATE.FAILED) { console.error('❌ WebRTC connection failed'); cleanupConnection(); } @@ -154,17 +155,17 @@ export const useWebRTC = (matchId, userId) => { const setupDataChannelHandlers = useCallback((dc) => { dc.onopen = () => { console.log('✅ DataChannel opened'); - setConnectionState('connected'); + setConnectionState(CONNECTION_STATE.CONNECTED); }; dc.onclose = () => { console.log('❌ DataChannel closed'); - setConnectionState('disconnected'); + setConnectionState(CONNECTION_STATE.DISCONNECTED); }; dc.onerror = (error) => { console.error('❌ DataChannel error:', error); - setConnectionState('failed'); + setConnectionState(CONNECTION_STATE.FAILED); }; dc.onmessage = (event) => { @@ -239,7 +240,7 @@ export const useWebRTC = (matchId, userId) => { */ const createOffer = useCallback(async () => { try { - setConnectionState('connecting'); + setConnectionState(CONNECTION_STATE.CONNECTING); const pc = initializePeerConnection(); createDataChannel(pc); @@ -257,7 +258,7 @@ export const useWebRTC = (matchId, userId) => { console.log('📤 Sent WebRTC offer'); } catch (error) { console.error('Failed to create offer:', error); - setConnectionState('failed'); + setConnectionState(CONNECTION_STATE.FAILED); } }, [initializePeerConnection, createDataChannel]); @@ -266,7 +267,7 @@ export const useWebRTC = (matchId, userId) => { */ const handleOffer = useCallback(async (offer) => { try { - setConnectionState('connecting'); + setConnectionState(CONNECTION_STATE.CONNECTING); const pc = initializePeerConnection(); @@ -293,7 +294,7 @@ export const useWebRTC = (matchId, userId) => { console.log('📤 Sent WebRTC answer'); } catch (error) { console.error('Failed to handle offer:', error); - setConnectionState('failed'); + setConnectionState(CONNECTION_STATE.FAILED); } }, [initializePeerConnection, setupDataChannelHandlers]); @@ -312,7 +313,7 @@ export const useWebRTC = (matchId, userId) => { console.log('✅ Remote description set (answer). ICE should connect now...'); } catch (error) { console.error('Failed to handle answer:', error); - setConnectionState('failed'); + setConnectionState(CONNECTION_STATE.FAILED); } }, []); @@ -414,7 +415,7 @@ export const useWebRTC = (matchId, userId) => { peerConnectionRef.current = null; } - setConnectionState('disconnected'); + setConnectionState(CONNECTION_STATE.DISCONNECTED); setIsTransferring(false); setTransferProgress(0); setReceivingFile(null); diff --git a/frontend/src/pages/MatchChatPage.jsx b/frontend/src/pages/MatchChatPage.jsx index c936686..fa1d6fe 100644 --- a/frontend/src/pages/MatchChatPage.jsx +++ b/frontend/src/pages/MatchChatPage.jsx @@ -14,6 +14,7 @@ import ChatInput from '../components/chat/ChatInput'; import useMatchChat from '../hooks/useMatchChat'; import FileTransferProgress from '../components/webrtc/FileTransferProgress'; import LinkShareInput from '../components/webrtc/LinkShareInput'; +import { CONNECTION_STATE } from '../constants'; const MatchChatPage = () => { const { slug } = useParams(); @@ -104,7 +105,7 @@ const MatchChatPage = () => { if (!selectedFile) return; // If not connected, initiate connection first - if (connectionState !== 'connected') { + if (connectionState !== CONNECTION_STATE.CONNECTED) { console.log('Creating WebRTC offer...'); await createOffer(); @@ -112,11 +113,11 @@ const MatchChatPage = () => { const waitForConnection = new Promise((resolve, reject) => { const timeout = setTimeout(() => reject(new Error('Connection timeout')), 30000); const checkConnection = setInterval(() => { - if (connectionState === 'connected') { + if (connectionState === CONNECTION_STATE.CONNECTED) { clearInterval(checkConnection); clearTimeout(timeout); resolve(); - } else if (connectionState === 'failed') { + } else if (connectionState === CONNECTION_STATE.FAILED) { clearInterval(checkConnection); clearTimeout(timeout); reject(new Error('Connection failed')); @@ -177,11 +178,11 @@ const MatchChatPage = () => { const getWebRTCStatusColor = () => { switch (connectionState) { - case 'connected': + case CONNECTION_STATE.CONNECTED: return 'text-green-600'; - case 'connecting': + case CONNECTION_STATE.CONNECTING: return 'text-yellow-600'; - case 'failed': + case CONNECTION_STATE.FAILED: return 'text-red-600'; default: return 'text-gray-400'; @@ -190,11 +191,11 @@ const MatchChatPage = () => { const getWebRTCStatusText = () => { switch (connectionState) { - case 'connected': + case CONNECTION_STATE.CONNECTED: return 'Connected (P2P)'; - case 'connecting': + case CONNECTION_STATE.CONNECTING: return 'Connecting...'; - case 'failed': + case CONNECTION_STATE.FAILED: return 'Connection failed'; default: return 'Ready to connect'; @@ -258,7 +259,7 @@ const MatchChatPage = () => { {/* WebRTC Status Bar */}
-
+
{getWebRTCStatusText()} @@ -270,7 +271,7 @@ const MatchChatPage = () => { )} - {connectionState === 'connected' ? '🔒 E2E Encrypted (DTLS)' : 'WebRTC P2P Ready'} + {connectionState === CONNECTION_STATE.CONNECTED ? 'E2E Encrypted (DTLS)' : 'WebRTC P2P Ready'}