pretty much ready to 'ship'.3
This commit is contained in:
@@ -2,7 +2,7 @@ export const branding = {
|
||||
app: {
|
||||
name: 'HSO Jackbox Game Picker',
|
||||
shortName: 'HSO JGP',
|
||||
version: '0.3.1',
|
||||
version: '0.3.2 - Safari Walkabout Edition',
|
||||
description: 'Spicing up Hyper Spaceout game nights!',
|
||||
},
|
||||
meta: {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
Reference in New Issue
Block a user