pretty much ready to 'ship'.2
This commit is contained in:
@@ -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: {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user