import React, { useState, useEffect, useCallback } from 'react'; import VotingBoard from '../VotingBoard'; import BoardCard from '../BoardCard'; import Results from '../Results'; import styles from './VotingTable.module.css'; import titleCardSrc from '../../assets/images/titlecard.png'; import { ReactComponent as ExitIcon } from '../../assets/images/exit.svg'; import { useNavigate, useParams } from 'react-router-dom'; import ProfileMenuButton from '../ProfileMenuButton'; import api from '../../services/api'; const VotingTable = ({ userId }) => { const [users, setUsers] = useState([]); const [votes, setVotes] = useState({}); const [, setVotedUsers] = useState(0); const [isFinal, setIsFinal] = useState(false); const { sessionId } = useParams(); const [currentUID, setCurrentUID] = useState(''); const navigate = useNavigate(); const maxUsers = 32; const username = users.find((user) => user.uid === currentUID)?.username || ''; const goToLobby = useCallback(() => { navigate(`/lobby/${sessionId}`); }, [sessionId, navigate]); async function handleLogout() { await handleDropUser(currentUID); } async function handleInvite() { try { navigator.clipboard.writeText(window.location.href); } catch (err) { console.error('Failed to copy invite link: ', err); } } const handleDropUser = async (userId) => { try { // Remove user vote and user from session via API calls await api.delete(`/api/session/${sessionId}/votes/${userId}`); await api.delete(`/api/session/${sessionId}/users/${userId}`); // Fetch updated session data after user removal const sessionResponse = await api.get(`/api/session/${sessionId}`); const sessionData = sessionResponse.data; if (!sessionData) return; // Update state with the new session data const userList = Object.entries(sessionData.users || {}).map( ([uid, userInfo]) => ({ uid, username: userInfo.username, }) ); setUsers(userList); setVotes(sessionData.votes || {}); // Redirect the dropped user to the lobby await api.post(`/api/users/${userId}`, { currentSessionId: `lobby/${sessionId}`, }); } catch (error) { console.error('Error removing user:', error); } }; const handleFinalizeVoting = async () => { try { // Finalize voting by setting the isFinal flag in the session via API call await api.post(`/api/session/${sessionId}/finalize`, { isFinal: true, }); setIsFinal(true); } catch (error) { console.error('Error finalizing voting:', error); } }; const handleResetVoting = async () => { try { // Reset the session's votes and isFinal flag via API call await api.post(`/api/session/${sessionId}/reset`, { votes: {}, isFinal: false, }); setVotes({}); setVotedUsers(0); setIsFinal(false); } catch (error) { console.error('Error resetting voting:', error); } }; useEffect(() => { const fetchSessionData = async () => { try { // Fetch session data from the API const sessionResponse = await api.get(`/api/session/${sessionId}`); const sessionData = sessionResponse.data; if (!sessionData) { // Initialize the session if it doesn't exist await api.post(`/api/session/${sessionId}`, { votes: {}, maxUsers: maxUsers, isFinal: false, users: {}, }); } else { // Load the existing session data const userList = Object.entries(sessionData.users || {}).map( ([uid, userInfo]) => ({ uid, username: userInfo.username, }) ); setUsers(userList); setVotes(sessionData.votes || {}); setIsFinal(sessionData.isFinal || false); } } catch (error) { console.error('Error fetching session data:', error); goToLobby(); // Redirect to lobby if the session doesn't exist } }; fetchSessionData(); // Polling or WebSocket could be used to listen for real-time updates const intervalId = setInterval(fetchSessionData, 5000); // Poll every 5 seconds return () => clearInterval(intervalId); // Clean up the interval }, [sessionId, maxUsers, navigate, setCurrentUID, goToLobby]); const allVoted = Object.values(votes).every((v) => v >= 0); return (
title-card
{users.map(({ uid, username }) => (
{ handleDropUser(uid) } title="Drop User" /> }
))}
{allVoted && !isFinal && (
Reveal Votes
)} {isFinal && (
Restart Voting
)}
{!isFinal ? ( ) : ( )}
); }; export default VotingTable;