From 3ec1808ad1f8f3ee646c90cfe9a29cd7dff570e2 Mon Sep 17 00:00:00 2001 From: Frank Tovar Date: Wed, 28 Jan 2026 16:58:18 +0100 Subject: [PATCH] Allow deleting own suggestions in Suggest phase and surface delete chip --- Program.cs | 16 ++++++++++++++++ wwwroot/app.js | 17 +++++++++++++++-- wwwroot/styles.css | 4 ++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Program.cs b/Program.cs index d427b18..52430e6 100644 --- a/Program.cs +++ b/Program.cs @@ -205,6 +205,22 @@ api.MapPost("/suggestions", async ([FromBody] SuggestionRequest request, HttpCon return Results.Created($"/api/suggestions/{suggestion.Id}", new { suggestion.Id }); }); +api.MapDelete("/suggestions/{id:int}", async (int id, HttpContext ctx, AppDbContext db) => +{ + var phase = await GetPhase(db); + if (phase != Phase.Suggest) + return PhaseMismatch(Phase.Suggest, phase); + + var player = await GetOrCreatePlayer(ctx, db); + var suggestion = await db.Suggestions.FirstOrDefaultAsync(s => s.Id == id && s.PlayerId == player.Id); + if (suggestion == null) + return Results.NotFound(new { error = "Suggestion not found." }); + + db.Suggestions.Remove(suggestion); + await db.SaveChangesAsync(); + return Results.NoContent(); +}); + api.MapGet("/suggestions/all", async (AppDbContext db) => { var phase = await GetPhase(db); diff --git a/wwwroot/app.js b/wwwroot/app.js index 2490b7a..399c33a 100644 --- a/wwwroot/app.js +++ b/wwwroot/app.js @@ -107,7 +107,7 @@ function renderMySuggestions() { const wrap = $("my-suggestions"); if (!wrap) return; wrap.innerHTML = ""; - state.mySuggestions.forEach((s) => wrap.appendChild(buildCard(s, { showAuthor: false }))); + state.mySuggestions.forEach((s) => wrap.appendChild(buildCard(s, { showAuthor: false, allowDelete: true }))); } function renderAllSuggestions() { @@ -289,7 +289,7 @@ async function refreshPhaseData() { await Promise.all([loadSuggestData(), loadRevealData(), loadVoteData(), loadResults()]); } -function buildCard(s, { showAuthor }) { +function buildCard(s, { showAuthor = false, allowDelete = false }) { const card = document.createElement("article"); card.className = "game-card"; const hasImage = !!s.screenshotUrl; @@ -304,6 +304,7 @@ function buildCard(s, { showAuthor }) { ${s.youtubeUrl ? `YouTube ↗` : ""}
${showAuthor && s.author ? `${s.author}` : ""} + ${allowDelete ? `` : ""}
${s.genre ? `

${s.genre}

` : ""} @@ -314,6 +315,18 @@ function buildCard(s, { showAuthor }) { const btn = card.querySelector(".card-visual"); btn.addEventListener("click", () => openLightbox(s.screenshotUrl, s.name)); } + if (allowDelete) { + const del = card.querySelector("[data-delete]"); + del.addEventListener("click", async () => { + try { + await api(`/api/suggestions/${s.id}`, { method: "DELETE" }); + toast("Suggestion deleted"); + await loadSuggestData(); + } catch (err) { + toast(err.message, true); + } + }); + } return card; } diff --git a/wwwroot/styles.css b/wwwroot/styles.css index 1909e5a..6fcf1a2 100644 --- a/wwwroot/styles.css +++ b/wwwroot/styles.css @@ -183,6 +183,10 @@ button.ghost { border-radius: 999px; font-size: 12px; } +.chip.danger-chip { + background: #dc2626; + border: 1px solid #b91c1c; +} .vote-controls { display: flex; gap: 10px; align-items: center; margin-top: 6px; } .score { font-weight: 700; }