Allow deleting own suggestions in Suggest phase and surface delete chip

This commit is contained in:
2026-01-28 16:58:18 +01:00
parent e6b341d837
commit 3ec1808ad1
3 changed files with 35 additions and 2 deletions

View File

@@ -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);

View File

@@ -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 ? `<a class="link compact" href="${s.youtubeUrl}" target="_blank" rel="noopener">YouTube ↗</a>` : ""}
<div class="title-meta">
${showAuthor && s.author ? `<span class="chip">${s.author}</span>` : ""}
${allowDelete ? `<button class="chip danger-chip" data-delete="${s.id}" type="button">Delete</button>` : ""}
</div>
</div>
${s.genre ? `<p class="muted">${s.genre}</p>` : ""}
@@ -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;
}

View File

@@ -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; }