feat: area admin con editor tiptap, api crud e upload immagini

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 01:49:12 +02:00
parent f3fb2fe005
commit f0ad162f74
14 changed files with 423 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
---
import Admin from '../../layouts/Admin.astro';
import { getDb } from '../../lib/db';
import { listAllPosts } from '../../lib/posts';
export const prerender = false;
const posts = listAllPosts(getDb());
const fmt = new Intl.DateTimeFormat('it-IT', { dateStyle: 'short', timeStyle: 'short' });
---
<Admin title="Articoli">
<h1>Articoli</h1>
<p><a class="abtn" href="/admin/new">+ Nuovo articolo</a></p>
<table>
<thead><tr><th>Titolo</th><th>Categoria</th><th>Stato</th><th>Aggiornato</th><th></th></tr></thead>
<tbody>
{posts.map((p) => (
<tr>
<td><a href={`/admin/edit/${p.id}`}>{p.title}</a></td>
<td>{p.category}</td>
<td><span class:list={['pill', { 'pill--draft': p.draft }]}>{p.draft ? 'Bozza' : 'Pubblicato'}</span></td>
<td>{fmt.format(new Date(p.updated_at.replace(' ', 'T') + 'Z'))}</td>
<td><button class="abtn abtn--danger" data-del={p.id}>Elimina</button></td>
</tr>
))}
</tbody>
</table>
{posts.length === 0 && <p>Nessun articolo: creane uno nuovo.</p>}
</Admin>
<script>
document.querySelectorAll<HTMLButtonElement>('[data-del]').forEach((b) =>
b.addEventListener('click', async () => {
if (!confirm('Eliminare definitivamente questo articolo?')) return;
const res = await fetch(`/api/admin/posts/${b.dataset.del}`, { method: 'DELETE' });
if (res.ok) location.reload();
else alert('Eliminazione non riuscita.');
}));
</script>