pretty much ready to 'ship'.3

This commit is contained in:
cottongin
2025-10-30 17:52:44 -04:00
parent 1a74b4d777
commit 47db3890e2
4 changed files with 119 additions and 94 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { useAuth } from '../context/AuthContext';
import { useToast } from '../components/Toast';
import api from '../api/axios';
@@ -17,9 +17,32 @@ function History() {
const [showAllSessions, setShowAllSessions] = useState(false);
const [deletingSession, setDeletingSession] = useState(null);
const loadSessions = useCallback(async () => {
try {
const response = await api.get('/sessions');
setSessions(response.data);
} catch (err) {
console.error('Failed to load sessions', err);
} finally {
setLoading(false);
}
}, []);
const refreshSessionGames = useCallback(async (sessionId, silent = false) => {
try {
const response = await api.get(`/sessions/${sessionId}/games`);
// Reverse chronological order (most recent first)
setSessionGames(response.data.reverse());
} catch (err) {
if (!silent) {
console.error('Failed to load session games', err);
}
}
}, []);
useEffect(() => {
loadSessions();
}, []);
}, [loadSessions]);
// Auto-select active session if navigating from picker
useEffect(() => {
@@ -29,7 +52,7 @@ function History() {
loadSessionGames(activeSession.id);
}
}
}, [sessions]);
}, [sessions, selectedSession]);
// Poll for session list updates (to detect when sessions end/start)
useEffect(() => {
@@ -38,7 +61,7 @@ function History() {
}, 3000);
return () => clearInterval(interval);
}, []);
}, [loadSessions]);
// Poll for updates on active session games
useEffect(() => {
@@ -49,22 +72,11 @@ function History() {
// Refresh games every 3 seconds for active session
const interval = setInterval(() => {
loadSessionGames(selectedSession, true); // silent refresh
refreshSessionGames(selectedSession, true); // silent refresh
}, 3000);
return () => clearInterval(interval);
}, [selectedSession, sessions]);
const loadSessions = async () => {
try {
const response = await api.get('/sessions');
setSessions(response.data);
} catch (err) {
console.error('Failed to load sessions', err);
} finally {
setLoading(false);
}
};
}, [selectedSession, sessions, refreshSessionGames]);
const handleExport = async (sessionId, format) => {
try {

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import api from '../api/axios';
@@ -11,21 +11,19 @@ function Home() {
const [sessionGames, setSessionGames] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadActiveSession();
const loadSessionGames = useCallback(async (sessionId, silent = false) => {
try {
const gamesResponse = await api.get(`/sessions/${sessionId}/games`);
// Reverse chronological order (most recent first)
setSessionGames(gamesResponse.data.reverse());
} catch (error) {
if (!silent) {
console.error('Failed to load session games', error);
}
}
}, []);
// Auto-refresh for active session status and games
useEffect(() => {
// Poll for session status changes every 3 seconds
const interval = setInterval(() => {
loadActiveSession();
}, 3000);
return () => clearInterval(interval);
}, []);
const loadActiveSession = async () => {
const loadActiveSession = useCallback(async () => {
try {
const response = await api.get('/sessions/active');
@@ -42,19 +40,21 @@ function Home() {
} finally {
setLoading(false);
}
};
}, [loadSessionGames]);
const loadSessionGames = async (sessionId, silent = false) => {
try {
const gamesResponse = await api.get(`/sessions/${sessionId}/games`);
// Reverse chronological order (most recent first)
setSessionGames(gamesResponse.data.reverse());
} catch (error) {
if (!silent) {
console.error('Failed to load session games', error);
}
}
};
useEffect(() => {
loadActiveSession();
}, [loadActiveSession]);
// Auto-refresh for active session status and games
useEffect(() => {
// Poll for session status changes every 3 seconds
const interval = setInterval(() => {
loadActiveSession();
}, 3000);
return () => clearInterval(interval);
}, [loadActiveSession]);
if (loading) {
return (

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import api from '../api/axios';
@@ -42,29 +42,31 @@ function Picker() {
// Exclude previously played games
const [excludePlayedGames, setExcludePlayedGames] = useState(false);
useEffect(() => {
// Wait for auth to finish loading before checking authentication
if (authLoading) return;
if (!isAuthenticated) {
navigate('/login');
return;
const checkActiveSession = useCallback(async () => {
try {
const sessionResponse = await api.get('/sessions/active');
const session = sessionResponse.data?.session !== undefined
? sessionResponse.data.session
: sessionResponse.data;
// Check if session status changed
setActiveSession(prevSession => {
// If we had a session but now don't, mark it as ended
if (prevSession && (!session || !session.id)) {
setSessionEnded(true);
return null;
} else if (session && session.id) {
setSessionEnded(false);
return session;
}
return prevSession;
});
} catch (err) {
console.error('Failed to check session status', err);
}
loadData();
}, [isAuthenticated, authLoading, navigate]);
}, []);
// Poll for active session status changes
useEffect(() => {
if (!isAuthenticated || authLoading) return;
const interval = setInterval(() => {
checkActiveSession();
}, 3000);
return () => clearInterval(interval);
}, [isAuthenticated, authLoading]);
const loadData = async () => {
const loadData = useCallback(async () => {
try {
// Load active session
const sessionResponse = await api.get('/sessions/active');
@@ -85,27 +87,29 @@ function Picker() {
} finally {
setLoading(false);
}
};
}, []);
const checkActiveSession = async () => {
try {
const sessionResponse = await api.get('/sessions/active');
const session = sessionResponse.data?.session !== undefined
? sessionResponse.data.session
: sessionResponse.data;
// If we had a session but now don't, mark it as ended
if (activeSession && (!session || !session.id)) {
setSessionEnded(true);
setActiveSession(null);
} else if (session && session.id) {
setActiveSession(session);
setSessionEnded(false);
}
} catch (err) {
console.error('Failed to check session status', err);
useEffect(() => {
// Wait for auth to finish loading before checking authentication
if (authLoading) return;
if (!isAuthenticated) {
navigate('/login');
return;
}
};
loadData();
}, [isAuthenticated, authLoading, navigate, loadData]);
// Poll for active session status changes
useEffect(() => {
if (!isAuthenticated || authLoading) return;
const interval = setInterval(() => {
checkActiveSession();
}, 3000);
return () => clearInterval(interval);
}, [isAuthenticated, authLoading, checkActiveSession]);
const handleCreateSession = async () => {
try {
@@ -727,11 +731,7 @@ function SessionInfo({ sessionId, onGamesUpdate }) {
const [confirmingRemove, setConfirmingRemove] = useState(null);
const [showPopularity, setShowPopularity] = useState(true);
useEffect(() => {
loadGames();
}, [sessionId, onGamesUpdate]);
const loadGames = async () => {
const loadGames = useCallback(async () => {
try {
const response = await api.get(`/sessions/${sessionId}/games`);
// Reverse chronological order (most recent first)
@@ -741,7 +741,20 @@ function SessionInfo({ sessionId, onGamesUpdate }) {
} finally {
setLoading(false);
}
};
}, [sessionId]);
useEffect(() => {
loadGames();
}, [sessionId, onGamesUpdate, loadGames]);
// Auto-refresh games list every 3 seconds
useEffect(() => {
const interval = setInterval(() => {
loadGames();
}, 3000);
return () => clearInterval(interval);
}, [loadGames]);
const handleUpdateStatus = async (gameId, newStatus) => {
try {
@@ -815,8 +828,8 @@ function SessionInfo({ sessionId, onGamesUpdate }) {
<p className="text-gray-500 dark:text-gray-400">No games played yet. Pick a game to get started!</p>
) : (
<div className="space-y-2 max-h-96 overflow-y-auto">
{games.map((game) => {
const index = games.length - games.indexOf(game);
{games.map((game, index) => {
const displayNumber = games.length - index;
return (
<div
key={game.id}
@@ -836,7 +849,7 @@ function SessionInfo({ sessionId, onGamesUpdate }) {
? 'text-gray-500 dark:text-gray-500 line-through'
: 'text-gray-700 dark:text-gray-200'
}`}>
{index + 1}. {game.title}
{displayNumber}. {game.title}
</span>
{getStatusBadge(game.status)}
{game.manually_added === 1 && (