Allow deleting own suggestions in Suggest phase and surface delete chip
This commit is contained in:
16
Program.cs
16
Program.cs
@@ -205,6 +205,22 @@ api.MapPost("/suggestions", async ([FromBody] SuggestionRequest request, HttpCon
|
|||||||
return Results.Created($"/api/suggestions/{suggestion.Id}", new { suggestion.Id });
|
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) =>
|
api.MapGet("/suggestions/all", async (AppDbContext db) =>
|
||||||
{
|
{
|
||||||
var phase = await GetPhase(db);
|
var phase = await GetPhase(db);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ function renderMySuggestions() {
|
|||||||
const wrap = $("my-suggestions");
|
const wrap = $("my-suggestions");
|
||||||
if (!wrap) return;
|
if (!wrap) return;
|
||||||
wrap.innerHTML = "";
|
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() {
|
function renderAllSuggestions() {
|
||||||
@@ -289,7 +289,7 @@ async function refreshPhaseData() {
|
|||||||
await Promise.all([loadSuggestData(), loadRevealData(), loadVoteData(), loadResults()]);
|
await Promise.all([loadSuggestData(), loadRevealData(), loadVoteData(), loadResults()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCard(s, { showAuthor }) {
|
function buildCard(s, { showAuthor = false, allowDelete = false }) {
|
||||||
const card = document.createElement("article");
|
const card = document.createElement("article");
|
||||||
card.className = "game-card";
|
card.className = "game-card";
|
||||||
const hasImage = !!s.screenshotUrl;
|
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>` : ""}
|
${s.youtubeUrl ? `<a class="link compact" href="${s.youtubeUrl}" target="_blank" rel="noopener">YouTube ↗</a>` : ""}
|
||||||
<div class="title-meta">
|
<div class="title-meta">
|
||||||
${showAuthor && s.author ? `<span class="chip">${s.author}</span>` : ""}
|
${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>
|
||||||
</div>
|
</div>
|
||||||
${s.genre ? `<p class="muted">${s.genre}</p>` : ""}
|
${s.genre ? `<p class="muted">${s.genre}</p>` : ""}
|
||||||
@@ -314,6 +315,18 @@ function buildCard(s, { showAuthor }) {
|
|||||||
const btn = card.querySelector(".card-visual");
|
const btn = card.querySelector(".card-visual");
|
||||||
btn.addEventListener("click", () => openLightbox(s.screenshotUrl, s.name));
|
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;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,10 @@ button.ghost {
|
|||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
.chip.danger-chip {
|
||||||
|
background: #dc2626;
|
||||||
|
border: 1px solid #b91c1c;
|
||||||
|
}
|
||||||
|
|
||||||
.vote-controls { display: flex; gap: 10px; align-items: center; margin-top: 6px; }
|
.vote-controls { display: flex; gap: 10px; align-items: center; margin-top: 6px; }
|
||||||
.score { font-weight: 700; }
|
.score { font-weight: 700; }
|
||||||
|
|||||||
Reference in New Issue
Block a user