diff --git a/public/admin.html b/public/admin.html new file mode 100644 index 0000000..930f412 --- /dev/null +++ b/public/admin.html @@ -0,0 +1,372 @@ + + + + + + Cabo Voting β€” Admin + + + + + +
+
+

πŸ” Admin Access

+

Enter the admin password to manage the voting app.

+ + +
+
+
+ + + +
+ + + + diff --git a/public/index.html b/public/index.html index 7633ff2..601bccc 100644 --- a/public/index.html +++ b/public/index.html @@ -780,6 +780,10 @@ renderTabs(); render(); } + } else if (msg.type === 'option_deleted') { + state.options = state.options.filter(o => o.id !== msg.id); + renderTabs(); + render(); } else if (msg.type === 'polls_status') { state.pollsOpen = msg.open; updatePollsBadge(); diff --git a/server.js b/server.js index 548e90b..5de8857 100644 --- a/server.js +++ b/server.js @@ -15,6 +15,12 @@ const DATA_FILE = path.join(DATA_DIR, 'votes.json'); app.use(cors()); app.use(express.json()); + +// Admin panel +app.get('/admin', (req, res) => { + res.sendFile(path.join(__dirname, 'public', 'admin.html')); +}); + app.use(express.static(path.join(__dirname, 'public'))); // ── Data helpers ────────────────────────────────────────────── @@ -189,6 +195,16 @@ app.post('/api/options/:id/approve', (req, res) => { res.json({ success: true }); }); +// Delete an option +app.delete('/api/options/:id', (req, res) => { + const idx = data.options.findIndex(o => o.id === req.params.id); + if (idx === -1) return res.status(404).json({ error: 'Not found' }); + data.options.splice(idx, 1); + saveData(data); + broadcast({ type: 'option_deleted', id: req.params.id }); + res.json({ success: true }); +}); + // Remove vote from an option app.delete('/api/vote/:optionId', (req, res) => { const { voterName } = req.body;