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'; /** * RecordingTab - Main component for managing recording partnerships * Shows suggestions for who will record user's heats and who user needs to record */ const RecordingTab = ({ slug, event, myHeats }) => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [suggestions, setSuggestions] = useState(null); const [recorderOptOut, setRecorderOptOut] = useState(false); const [updatingOptOut, setUpdatingOptOut] = useState(false); const [runningMatching, setRunningMatching] = useState(false); // Load suggestions on mount useEffect(() => { loadSuggestions(); }, [slug]); const loadSuggestions = async () => { try { setLoading(true); setError(null); const data = await matchingAPI.getSuggestions(slug); setSuggestions(data); } catch (err) { console.error('Failed to load suggestions:', err); setError('Nie udalo sie zaladowac sugestii'); } finally { setLoading(false); } }; const handleOptOutChange = async (newValue) => { try { setUpdatingOptOut(true); await matchingAPI.setRecorderOptOut(slug, newValue); setRecorderOptOut(newValue); } catch (err) { console.error('Failed to update opt-out:', err); } finally { setUpdatingOptOut(false); } }; const handleUpdateStatus = async (suggestionId, status) => { try { await matchingAPI.updateSuggestionStatus(slug, suggestionId, status); // Reload suggestions await loadSuggestions(); } catch (err) { console.error('Failed to update suggestion status:', err); } }; const handleRunMatching = async () => { try { setRunningMatching(true); await matchingAPI.runMatching(slug); await loadSuggestions(); } catch (err) { console.error('Failed to run matching:', err); } finally { setRunningMatching(false); } }; // Calculate countdown to matching const getCountdown = () => { if (!event?.registrationDeadline) return null; const deadline = new Date(event.registrationDeadline); const now = new Date(); const diff = deadline.getTime() - now.getTime(); if (diff <= 0) return null; const hours = Math.floor(diff / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); return { hours, minutes }; }; if (loading) { return (

Ladowanie...

); } if (error) { return (
{error}
); } const countdown = getCountdown(); const toBeRecorded = suggestions?.toBeRecorded || []; const toRecord = suggestions?.toRecord || []; const matchingRunAt = suggestions?.matchingRunAt; return (
{/* Header with info */}

System automatycznie dobiera osoby do wzajemnego nagrywania wystepow.

{/* Countdown or Status */} {countdown ? (

Matching uruchomi sie za: {countdown.hours}h {countdown.minutes}min

Po zamknieciu zapisow system automatycznie dobierze partnerow do nagrywania.

) : matchingRunAt ? (

Matching zakonczony

Ostatnie uruchomienie: {new Date(matchingRunAt).toLocaleString('pl-PL')}

) : (

Matching nie zostal jeszcze uruchomiony

)} {/* My heats to be recorded */}

{toBeRecorded.length === 0 ? (
{myHeats.length === 0 ? 'Nie masz zadeklarowanych heatow' : 'Brak sugestii - uruchom matching' }
) : (
{toBeRecorded.map((suggestion) => ( handleUpdateStatus(suggestion.id, 'accepted')} onReject={() => handleUpdateStatus(suggestion.id, 'rejected')} /> ))}
)}
{/* Heats I need to record */}

Nagrywam innych ({toRecord.length})

{toRecord.length === 0 ? (
Nie masz przypisanych heatow do nagrywania
) : (
{toRecord.map((suggestion) => ( handleUpdateStatus(suggestion.id, 'accepted')} onReject={() => handleUpdateStatus(suggestion.id, 'rejected')} /> ))}
)}
{/* Opt-out toggle */}

Jesli zaznaczysz, spadniesz na koniec kolejki przy przydzielaniu partnerow.

); }; /** * SuggestionCard - Single suggestion item */ const SuggestionCard = ({ suggestion, type, onAccept, onReject }) => { const heat = suggestion.heat; const recorder = suggestion.recorder; const dancer = heat?.user; const status = suggestion.status; // Format heat info const heatInfo = heat ? `${heat.division?.abbreviation || '?'} ${heat.competitionType?.abbreviation || '?'} H${heat.heatNumber}` : 'Unknown heat'; const person = type === 'toBeRecorded' ? recorder : dancer; const personLabel = type === 'toBeRecorded' ? 'Nagrywa Cie:' : 'Nagrywasz:'; // Status badge const getStatusBadge = () => { switch (status) { case 'accepted': return ( Zaakceptowano ); case 'rejected': return ( Odrzucono ); case 'not_found': return ( Nie znaleziono ); default: return null; } }; // No recorder found if (status === 'not_found') { return (

{heatInfo}

Nie znaleziono dostepnego partnera

{getStatusBadge()}
); } return (
{person ? ( ) : (
)}

{heatInfo}

{personLabel} @{person?.username || '?'} {person?.city && ( ({person.city}) )}

{status === 'pending' ? ( <> ) : ( getStatusBadge() )}
); }; export default RecordingTab;