diff --git a/server.js b/server.js index 01d47ce..89bc234 100644 --- a/server.js +++ b/server.js @@ -1,16 +1,14 @@ /* server.js - - - "Solo" and "Together" arrays: - - Start with 5 each, index 0..4 are "base" points. - - Additional "earned" points are appended (index >= 5). - - Weekly reset => set ALL items to false (keep array lengths). - - POST /add-points => appends new "false" items to "soloUsed" or "togetherUsed". - - Admin route: /admin/remove-all-earned => remove appended points beyond index 4 in both arrays. + A single Node/Express server that: + 1) Manages timers, logs, admin routes (same logic as before). + 2) Serves the React build from "client/build". */ const express = require('express'); const cors = require('cors'); +const path = require('path'); // for serving the React build +const app = express(); // ----- CONFIG ----- const PORT = 4000; @@ -37,7 +35,7 @@ let logs = []; let lastReset = null; -// Timer +// Timer state let timerRunning = false; let timeRemaining = 0; let isPaused = false; @@ -84,18 +82,21 @@ setInterval(() => { } }, 1000); -// ----- EXPRESS ----- -const app = express(); +// ----------------------------- +// EXPRESS / MIDDLEWARE +// ----------------------------- app.use(cors()); app.use(express.json()); -// Weekly reset check +// Weekly reset check on each request app.use((req, res, next) => { resetIfNewWeek(); next(); }); -// GET /state => entire state +// ----------------------------- +// API ROUTES +// ----------------------------- app.get('/state', (req, res) => { res.json({ soloUsed, @@ -110,7 +111,7 @@ app.get('/state', (req, res) => { }); }); -// POST /use-bubble => single bubble => 15-min +// Single bubble => 15-min timer app.post('/use-bubble', (req, res) => { const { category, index } = req.body; @@ -153,7 +154,7 @@ app.post('/use-bubble', (req, res) => { return res.json({ success: true }); }); -// POST /check-password => new endpoint to quickly validate POINTS_PASSWORD +// Check password quickly app.post('/check-password', (req, res) => { const { password } = req.body; if (password !== POINTS_PASSWORD) { @@ -162,11 +163,9 @@ app.post('/check-password', (req, res) => { return res.json({ success: true }); }); -// POST /add-points => appends "amount" new false items to soloUsed/togetherUsed +// Add points => appends "amount" new false items to solo/together app.post('/add-points', (req, res) => { const { password, category, amount } = req.body; - // We could re-check password if we want. - // If you rely on /check-password, then skip here or just do it again: if (password !== POINTS_PASSWORD) { return res.status(403).json({ error: 'Incorrect password.' }); } @@ -257,7 +256,6 @@ app.post('/use-movie', (req, res) => { return res.status(400).json({ error: 'A chosen point is already used.' }); } } - // Mark used for (const p of chosenPoints) { let arr = p.category === 'solo' ? soloUsed : togetherUsed; arr[p.index] = true; @@ -287,7 +285,7 @@ app.post('/use-episode', (req, res) => { } const usedAt = new Date().toISOString(); logs.push({ type: 'episode', index: null, usedAt }); - console.log('[Server] Episode => used 2 chosen points at', usedAt); + console.log('[Server] Episode => used 2 points at', usedAt); return res.json({ success: true }); }); @@ -305,23 +303,18 @@ app.post('/admin/clear-logs', (req, res) => { res.json({ success: true }); }); app.post('/admin/reset-usage', (req, res) => { - // Keep array lengths, set all to false soloUsed = soloUsed.map(() => false); togetherUsed = togetherUsed.map(() => false); console.log('[Server] Usage reset by admin => all set false, arrays kept'); res.json({ success: true }); }); - -// This new route removes all appended points from both arrays, leaving the base 5 app.post('/admin/remove-all-earned', (req, res) => { - // Keep only the first 5 in each array + // keep only first 5 in each array soloUsed.splice(5); togetherUsed.splice(5); console.log('[Server] All earned points removed => each array back to length 5'); res.json({ success: true }); }); - -// For demonstration, these add/remove 1 from "soloUsed" app.post('/admin/add-earned', (req, res) => { soloUsed.push(false); console.log('[Server] Admin +1 to soloUsed => length now', soloUsed.length); @@ -335,7 +328,6 @@ app.post('/admin/remove-earned', (req, res) => { console.log('[Server] Admin removed last from soloUsed => length now', soloUsed.length); res.json({ success: true }); }); - app.post('/admin/clear-timer', (req, res) => { timerRunning = false; timeRemaining = 0; @@ -353,6 +345,16 @@ app.post('/admin/expire-timer', (req, res) => { res.json({ success: true }); }); +// ----------------------------- +// SERVE REACT BUILD +// ----------------------------- +app.use(express.static(path.join(__dirname, 'client', 'build'))); + +// Catch-all to serve index.html for any unknown route +app.get('*', (req, res) => { + res.sendFile(path.join(__dirname, 'client', 'build', 'index.html')); +}); + // Start server app.listen(PORT, () => { console.log(`[Server] Listening on port ${PORT}`);