pretty much ready to 'ship'.2

This commit is contained in:
cottongin
2025-10-30 17:34:44 -04:00
parent 8f3a12ad76
commit 1a74b4d777
4 changed files with 92 additions and 17 deletions

View File

@@ -2,7 +2,7 @@ export const branding = {
app: { app: {
name: 'HSO Jackbox Game Picker', name: 'HSO Jackbox Game Picker',
shortName: 'HSO JGP', shortName: 'HSO JGP',
version: '0.3.0', version: '0.3.1',
description: 'Spicing up Hyper Spaceout game nights!', description: 'Spicing up Hyper Spaceout game nights!',
}, },
meta: { meta: {

View File

@@ -31,7 +31,16 @@ function History() {
} }
}, [sessions]); }, [sessions]);
// Poll for updates on active session // Poll for session list updates (to detect when sessions end/start)
useEffect(() => {
const interval = setInterval(() => {
loadSessions();
}, 3000);
return () => clearInterval(interval);
}, []);
// Poll for updates on active session games
useEffect(() => { useEffect(() => {
if (!selectedSession) return; if (!selectedSession) return;

View File

@@ -15,17 +15,15 @@ function Home() {
loadActiveSession(); loadActiveSession();
}, []); }, []);
// Auto-refresh for active session // Auto-refresh for active session status and games
useEffect(() => { useEffect(() => {
if (!activeSession) return; // Poll for session status changes every 3 seconds
// Refresh games every 3 seconds for active session
const interval = setInterval(() => { const interval = setInterval(() => {
loadSessionGames(activeSession.id, true); // silent refresh loadActiveSession();
}, 3000); }, 3000);
return () => clearInterval(interval); return () => clearInterval(interval);
}, [activeSession]); }, []);
const loadActiveSession = async () => { const loadActiveSession = async () => {
try { try {

View File

@@ -17,6 +17,7 @@ function Picker() {
const [picking, setPicking] = useState(false); const [picking, setPicking] = useState(false);
const [error, setError] = useState(''); const [error, setError] = useState('');
const [showPopularity, setShowPopularity] = useState(true); const [showPopularity, setShowPopularity] = useState(true);
const [sessionEnded, setSessionEnded] = useState(false);
// Filters // Filters
const [playerCount, setPlayerCount] = useState(''); const [playerCount, setPlayerCount] = useState('');
@@ -52,9 +53,20 @@ function Picker() {
loadData(); loadData();
}, [isAuthenticated, authLoading, navigate]); }, [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 = async () => {
try { try {
// Load active session or create one // Load active session
const sessionResponse = await api.get('/sessions/active'); const sessionResponse = await api.get('/sessions/active');
// Handle new format { session: null } or old format (direct session object) // Handle new format { session: null } or old format (direct session object)
@@ -62,12 +74,7 @@ function Picker() {
? sessionResponse.data.session ? sessionResponse.data.session
: sessionResponse.data; : sessionResponse.data;
// If no active session, create one // Don't auto-create session - let user create it explicitly
if (!session || !session.id) {
const newSession = await api.post('/sessions', {});
session = newSession.data;
}
setActiveSession(session); setActiveSession(session);
// Load all games for manual selection // Load all games for manual selection
@@ -80,6 +87,37 @@ function Picker() {
} }
}; };
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);
}
};
const handleCreateSession = async () => {
try {
const newSession = await api.post('/sessions', {});
setActiveSession(newSession.data);
setSessionEnded(false);
setError('');
} catch (err) {
setError('Failed to create session');
}
};
const loadEligibleGames = async () => { const loadEligibleGames = async () => {
try { try {
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -246,8 +284,38 @@ function Picker() {
if (!activeSession) { if (!activeSession) {
return ( return (
<div className="max-w-4xl mx-auto"> <div className="max-w-4xl mx-auto">
<div className="bg-red-100 dark:bg-red-900 border border-red-400 dark:border-red-700 text-red-700 dark:text-red-200 p-4 rounded"> <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6">
Failed to load or create session. Please try again. {sessionEnded ? (
<>
<h2 className="text-2xl font-bold text-orange-600 dark:text-orange-400 mb-4">
Session Ended
</h2>
<p className="text-gray-700 dark:text-gray-300 mb-4">
The active session has been ended. To continue picking games, you'll need to create a new session.
</p>
<button
onClick={handleCreateSession}
className="bg-indigo-600 dark:bg-indigo-700 text-white px-6 py-3 rounded-lg hover:bg-indigo-700 dark:hover:bg-indigo-800 transition font-semibold"
>
Create New Session
</button>
</>
) : (
<>
<h2 className="text-2xl font-bold text-gray-700 dark:text-gray-200 mb-4">
No Active Session
</h2>
<p className="text-gray-600 dark:text-gray-400 mb-4">
There is no active game session. Create a new session to start picking games.
</p>
<button
onClick={handleCreateSession}
className="bg-indigo-600 dark:bg-indigo-700 text-white px-6 py-3 rounded-lg hover:bg-indigo-700 dark:hover:bg-indigo-800 transition font-semibold"
>
Create New Session
</button>
</>
)}
</div> </div>
</div> </div>
); );