From 787a094c59f2330f5af1e420eab6139b8aadb8be Mon Sep 17 00:00:00 2001 From: khalil Date: Thu, 13 Aug 2026 21:17:15 +0000 Subject: [PATCH] fix(api,frontend): delete is the true inverse of adopt, no reseed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /creatures/:id/delete now just removes the row, matching how POST /creatures (adopt) just inserts one — no side effects on anything else. The auto-reseed was scope creep for a feature that only ever made sense as a public marketing-site action; now that delete lives in the app itself as a per-creature control, that safety net isn't needed. Adds a Delete button next to Feed/Play/Sleep/Revive on every creature card, same creatureAction() plumbing as the existing actions. --- api/server.js | 26 ++++++-------------------- frontend/app.js | 5 +++++ frontend/style.css | 8 ++++++++ 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/api/server.js b/api/server.js index 821bd5d..c7ddb9b 100644 --- a/api/server.js +++ b/api/server.js @@ -368,14 +368,11 @@ app.post('/api/creatures/:id/kill', async (req, res) => { } }); -// POST /creatures/:id/delete — Permanently delete a creature (Chaos Button -// demo). Unlike /kill, this never touches tamagotchi_creatures_dead_total — -// the row is gone, not marked dead — so it does NOT trigger the Prometheus -// alert or n8n. That's intentional: it demonstrates a different resilience -// layer, the app defending its own roster instead of relying on external -// monitoring automation. A public, unauthenticated action that only ever -// shrinks the roster would eventually empty it, so a replacement hatches -// immediately. +// POST /creatures/:id/delete — Permanently delete a creature. The exact +// inverse of POST /creatures (adopt): adopt inserts a row with no side +// effects on anything else, delete removes one the same way — no reseed, +// no gauge update. It never touches tamagotchi_creatures_dead_total, so it +// does not trigger the Prometheus alert or n8n; deleting is not dying. app.post('/api/creatures/:id/delete', async (req, res) => { try { const { rows } = await pool.query('SELECT * FROM creatures WHERE id = $1', [req.params.id]); @@ -385,18 +382,7 @@ app.post('/api/creatures/:id/delete', async (req, res) => { await pool.query('DELETE FROM creatures WHERE id = $1', [req.params.id]); - const seedNames = ['Pixel', 'Nimbus', 'Sprocket', 'Blossom', 'Byte', 'Echo', 'Flux', 'Glitch']; - const allowedTypes = ['dragon', 'cat', 'robot', 'plant', 'alien']; - const newId = uuidv4(); - const newName = seedNames[Math.floor(Math.random() * seedNames.length)]; - const newType = allowedTypes[Math.floor(Math.random() * allowedTypes.length)]; - await pool.query('INSERT INTO creatures (id, name, type) VALUES ($1, $2, $3)', [newId, newName, newType]); - - const result = await pool.query('SELECT * FROM creatures WHERE id = $1', [newId]); - res.json({ - message: `${deletedName} was deleted permanently. ${newName} the ${newType} hatched to take its place 🥚`, - creature: result.rows[0] - }); + res.json({ message: `${deletedName} has been deleted permanently 🗑️` }); } catch (err) { res.status(500).json({ error: err.message }); } diff --git a/frontend/app.js b/frontend/app.js index c00dd36..6b9ccca 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -29,6 +29,8 @@ const i18n = { play: '🎮 Play', sleep: '💤 Sleep', revive: '✨ Revive', + delete: '🗑️', + delete_title: 'Delete permanently — the opposite of Adopt', alive: 'Alive', dead: 'Dead', empty_title: 'No creatures yet!', @@ -47,6 +49,8 @@ const i18n = { play: '🎮 Jouer', sleep: '💤 Dormir', revive: '✨ Ressusciter', + delete: '🗑️', + delete_title: "Supprimer definitivement — l'oppose d'Adopter", alive: 'Vivant', dead: 'Mort', empty_title: 'Pas encore de créatures !', @@ -226,6 +230,7 @@ function renderCreatures() { ` : ` `} + `; diff --git a/frontend/style.css b/frontend/style.css index a8ffe53..175ebc0 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -295,6 +295,14 @@ body::before { color: var(--accent-green); } +.action-btn.delete { + background: rgba(255, 68, 102, 0.1); + border-color: rgba(255, 68, 102, 0.2); + color: var(--accent-red); + flex: 0 0 auto; + width: 44px; +} + /* ---- FAB ---- */ .fab { position: fixed;