diff --git a/data/wordlists.json b/data/wordlists.json index 78d247e..c46a608 100644 --- a/data/wordlists.json +++ b/data/wordlists.json @@ -11,13 +11,27 @@ "bot", "snot" ], - "nate": [ - "computer", - "keyboard", - "mouse", - "screen", - "printer" - ], + "nate": { + "weeks": [ + { + "date": "2025-08-03", + "words": [ + "not", + "bot", + "snot" + ] + }, + { + "date": "2025-08-10", + "words": [ + "bate", + "hate", + "late" + ] + } + ], + "activeWeek": "2025-08-10" + }, "testuser": [ "hello", "world", diff --git a/public/js/admin.js b/public/js/admin.js index cf196d1..8e33bf3 100644 --- a/public/js/admin.js +++ b/public/js/admin.js @@ -293,9 +293,35 @@ async function loadWordsForSelectedUser() { const selectedUser = document.getElementById("wordUserSelect").value; if (!selectedUser) return; + // Fetch the user's word list object (could be array or {weeks, activeWeek}) const res = await fetch(`/getWordList?username=${encodeURIComponent(selectedUser)}`); const data = await res.json(); allWords = data.words || []; + // Now also fetch the raw wordlists object to get weeks/activeWeek + const wordlistsRes = await fetch('/getWordlistsRaw'); + const wordlists = await wordlistsRes.json(); + const userList = wordlists[selectedUser]; + // If userList is an object with weeks, populate week cards and dropdown + if (userList && typeof userList === 'object' && Array.isArray(userList.weeks)) { + // Clear current week cards + document.getElementById('weeksContainer').innerHTML = ''; + userList.weeks.forEach(week => { + window.addWeekInput(); + const cards = document.querySelectorAll('#weeksContainer .week-input-card'); + const lastCard = cards[cards.length - 1]; + if (lastCard) { + lastCard.querySelector('.week-date').value = week.date; + lastCard.querySelector('.week-words').value = (week.words || []).join('\n'); + } + }); + // Repopulate the active week dropdown + window.populateActiveWeekDropdown(); + // Set the dropdown to the saved activeWeek if present + if (userList.activeWeek) { + const select = document.getElementById('activeWeekSelect'); + select.value = userList.activeWeek; + } + } displayWordList(); } diff --git a/server.js b/server.js index 65fa3bc..d4c1cf8 100644 --- a/server.js +++ b/server.js @@ -4,6 +4,12 @@ const path = require('path'); const app = express(); const PORT = 3000; +// Serve raw wordlists.json for admin UI (must come after app is defined) +app.get('/getWordlistsRaw', (req, res) => { + const wordlists = readJsonSafe(path.join(DATA_DIR, files.wordlists), {}); + res.json(wordlists); +}); + // 📁 Static assets app.use(express.static('public')); app.use(express.json()); @@ -285,9 +291,23 @@ app.get('/getWordList', (req, res) => { console.log('Available wordlists:', Object.keys(wordLists)); // Get words for specific user - const userWords = wordLists[username] || []; + let userWords = wordLists[username] || []; + // If the user's word list is an object (weeks/activeWeek) + if (userWords && typeof userWords === 'object' && !Array.isArray(userWords)) { + if (Array.isArray(userWords.weeks)) { + // If activeWeek is set, return only that week's words + if (userWords.activeWeek) { + const found = userWords.weeks.find(w => w.date === userWords.activeWeek); + userWords = found && Array.isArray(found.words) ? found.words : []; + } else { + // No activeWeek, flatten all words from all weeks + userWords = userWords.weeks.flatMap(w => Array.isArray(w.words) ? w.words : []); + } + } else { + userWords = []; + } + } console.log(`Words found for ${username}:`, userWords); - res.json({ words: userWords }); } catch (error) { console.error('Error in getWordList:', error); @@ -295,47 +315,8 @@ app.get('/getWordList', (req, res) => { } }); +// Save a word list for a user app.post('/saveWordList', (req, res) => { -// Save multiple weeks with dates for a user -app.post('/saveWeeksWordList', (req, res) => { -// Set active week for a user -app.post('/setActiveWeek', (req, res) => { - const { username, activeWeek } = req.body; - if (typeof username !== 'string' || typeof activeWeek !== 'string') { - return res.status(400).send('Invalid data'); - } - const wordlistsPath = path.join(DATA_DIR, files.wordlists); - const wordlists = readJsonSafe(wordlistsPath); - if (!wordlists[username]) { - return res.status(404).send('User not found'); - } - if (typeof wordlists[username] === 'object') { - wordlists[username].activeWeek = activeWeek; - } else { - wordlists[username] = { weeks: [], activeWeek }; - } - fs.writeFileSync(wordlistsPath, JSON.stringify(wordlists, null, 2)); - res.send(`✅ Active week set for ${username}: ${activeWeek}`); -}); - const { username, weeks } = req.body; - if ( - typeof username !== 'string' || - !Array.isArray(weeks) || - weeks.length > 100 || - weeks.some(w => typeof w.date !== 'string' || !Array.isArray(w.words) || w.words.some(word => typeof word !== 'string')) - ) return res.status(400).send('Invalid weeks data'); - - const userList = readJsonSafe(path.join(DATA_DIR, files.users), []); - if (!userList.find(u => u.username === username)) { - return res.status(404).send('User not found'); - } - - const wordlistsPath = path.join(DATA_DIR, files.wordlists); - const wordlists = readJsonSafe(wordlistsPath); - wordlists[username] = { weeks }; - fs.writeFileSync(wordlistsPath, JSON.stringify(wordlists, null, 2)); - res.send(`✅ Weeks word list saved for ${username}`); -}); const { username, words } = req.body; if ( typeof username !== 'string' || @@ -356,6 +337,47 @@ app.post('/setActiveWeek', (req, res) => { res.send(`✅ Word list saved for ${username}`); }); +// Save multiple weeks with dates for a user +app.post('/saveWeeksWordList', (req, res) => { + const { username, weeks } = req.body; + if ( + typeof username !== 'string' || + !Array.isArray(weeks) || + weeks.length > 100 || + weeks.some(w => typeof w.date !== 'string' || !Array.isArray(w.words) || w.words.some(word => typeof word !== 'string')) + ) return res.status(400).send('Invalid weeks data'); + + const userList = readJsonSafe(path.join(DATA_DIR, files.users), []); + if (!userList.find(u => u.username === username)) { + return res.status(404).send('User not found'); + } + + const wordlistsPath = path.join(DATA_DIR, files.wordlists); + const wordlists = readJsonSafe(wordlistsPath); + wordlists[username] = { weeks }; + fs.writeFileSync(wordlistsPath, JSON.stringify(wordlists, null, 2)); + res.send(`✅ Weeks word list saved for ${username}`); +}); + +// Set active week for a user +app.post('/setActiveWeek', (req, res) => { + const { username, activeWeek } = req.body; + if (typeof username !== 'string' || typeof activeWeek !== 'string') { + return res.status(400).send('Invalid data'); + } + const wordlistsPath = path.join(DATA_DIR, files.wordlists); + const wordlists = readJsonSafe(wordlistsPath); + if (!wordlists[username] || typeof wordlists[username] !== 'object') { + return res.status(404).send('User not found or no weeks data'); + } + wordlists[username].activeWeek = activeWeek; + fs.writeFileSync(wordlistsPath, JSON.stringify(wordlists, null, 2)); + res.send(`✅ Active week set for ${username}: ${activeWeek}`); +}); + +// Set active week for a user +// ...existing code... + // 📊 Results app.get('/getResults', (req, res) => { const results = readJsonSafe(path.join(DATA_DIR, files.results));