ideas: add done/reopen status toggle for admins

Admin-only POST /api/ideas/{id}/status toggles status between open and
done. Done ideas are greyed out (opacity 0.55), show a green checkmark,
and sink to the bottom of the list. Admins see done/reopen buttons on
each card.
This commit is contained in:
Davide Scaini
2026-05-13 19:32:30 +02:00
parent 38f2e51788
commit c30a15d295
2 changed files with 66 additions and 11 deletions
+43 -10
View File
@@ -10,6 +10,7 @@
votes: string[];
vote_count: number;
my_vote: boolean;
status?: string;
}
let ideas: Idea[] = [];
@@ -108,6 +109,22 @@
}
}
async function toggleStatus(idea: Idea) {
const r = await fetch(`/api/ideas/${idea.id}/status`, {
method: 'POST',
credentials: 'include',
});
if (r.ok) {
const d = await r.json();
idea.status = d.status;
ideas = [...ideas].sort((a, b) =>
(a.status === 'done' ? 1 : 0) - (b.status === 'done' ? 1 : 0) ||
b.vote_count - a.vote_count ||
b.created_at - a.created_at
);
}
}
async function deleteIdea(idea: Idea) {
if (!confirm(`Delete "${idea.title}"?`)) return;
const r = await fetch(`/api/ideas/${idea.id}`, {
@@ -170,7 +187,11 @@
{:else}
<ul class="space-y-3">
{#each ideas as idea (idea.id)}
<li class="rounded-xl border px-4 py-3 flex gap-3" style="background: var(--bg-card); border-color: var(--border)">
{@const done = idea.status === 'done'}
<li
class="rounded-xl border px-4 py-3 flex gap-3 transition-opacity"
style="background: var(--bg-card); border-color: var(--border); opacity: {done ? '0.55' : '1'}"
>
<!-- Vote button -->
<div class="flex flex-col items-center shrink-0 pt-0.5">
<button
@@ -189,15 +210,27 @@
<!-- Content -->
<div class="flex-1 min-w-0">
<div class="flex items-start justify-between gap-2">
<p class="font-medium text-sm" style="color: var(--text-primary)">{idea.title}</p>
{#if isAdmin || idea.author === myHandle}
<button
on:click={() => deleteIdea(idea)}
class="shrink-0 text-xs px-1.5 py-0.5 rounded transition-colors hover:text-red-400"
style="color: var(--text-5)"
title="Delete"
>×</button>
{/if}
<p class="font-medium text-sm" style="color: var(--text-primary)">
{#if done}<span class="mr-1.5 text-green-500"></span>{/if}{idea.title}
</p>
<div class="flex items-center gap-1 shrink-0">
{#if isAdmin}
<button
on:click={() => toggleStatus(idea)}
class="text-xs px-1.5 py-0.5 rounded transition-colors"
style="color: {done ? 'var(--text-5)' : 'var(--accent)'}; border: 1px solid {done ? 'var(--border-sub)' : 'var(--accent)'}"
title={done ? 'Mark as open' : 'Mark as done'}
>{done ? 'reopen' : 'done'}</button>
{/if}
{#if isAdmin || idea.author === myHandle}
<button
on:click={() => deleteIdea(idea)}
class="text-xs px-1.5 py-0.5 rounded transition-colors hover:text-red-400"
style="color: var(--text-5)"
title="Delete"
>×</button>
{/if}
</div>
</div>
{#if idea.body}
<p class="text-xs mt-1" style="color: var(--text-4)">{idea.body}</p>