93 lines
2.6 KiB
Text
93 lines
2.6 KiB
Text
---
|
|
export const prerender = false;
|
|
|
|
import { getSession } from 'auth-astro/server';
|
|
import { getPendingEntries, type GuestbookEntry } from '../lib/db';
|
|
import { isAdmin } from '../lib/auth';
|
|
import Layout from '../layouts/Layout.astro';
|
|
|
|
let session;
|
|
try {
|
|
session = await getSession(Astro.request);
|
|
} catch {
|
|
return new Response('Auth not configured', { status: 500 });
|
|
}
|
|
|
|
if (!session) {
|
|
return Astro.redirect('/api/auth/signin');
|
|
}
|
|
|
|
if (!isAdmin(session.user?.id)) {
|
|
return new Response('Forbidden', { status: 403 });
|
|
}
|
|
|
|
let entries: GuestbookEntry[] = [];
|
|
try {
|
|
entries = await getPendingEntries();
|
|
} catch {
|
|
// handle error
|
|
}
|
|
|
|
function formatDate(date: Date): string {
|
|
const d = String(date.getDate()).padStart(2, '0');
|
|
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
const y = String(date.getFullYear()).slice(-2);
|
|
return `${d}/${m}/${y}`;
|
|
}
|
|
---
|
|
<Layout title="admin - guestbook" showHeader={false}>
|
|
|
|
<h1>guestbook admin</h1>
|
|
<p>logged in as {session.user?.name} <a href="/api/auth/signout">sign out</a></p>
|
|
|
|
<p><button id="deploy">redeploy site</button> <span id="deploy-status"></span></p>
|
|
|
|
{entries.length === 0 ? (
|
|
<p class="muted">no pending entries</p>
|
|
) : (
|
|
<ul id="entries">
|
|
{entries.map(e => (
|
|
<li data-id={e.id}>
|
|
<span class="muted">{formatDate(e.createdAt)}</span>
|
|
<strong>{e.name}</strong>
|
|
{e.url && <a href={e.url}>{e.url}</a>}
|
|
<p>{e.message}</p>
|
|
<button class="approve">approve</button>
|
|
<button class="reject">reject</button>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
|
|
<script>
|
|
document.getElementById('deploy')?.addEventListener('click', async (e) => {
|
|
const btn = e.target as HTMLButtonElement;
|
|
const status = document.getElementById('deploy-status');
|
|
btn.disabled = true;
|
|
if (status) status.textContent = 'deploying...';
|
|
|
|
const res = await fetch('/api/deploy', { method: 'POST' });
|
|
if (res.ok) {
|
|
if (status) status.textContent = 'deploy triggered!';
|
|
} else {
|
|
const data = await res.json();
|
|
if (status) status.textContent = data.error || 'deploy failed';
|
|
}
|
|
btn.disabled = false;
|
|
});
|
|
|
|
document.querySelectorAll('#entries li').forEach(li => {
|
|
const id = li.getAttribute('data-id');
|
|
|
|
li.querySelector('.approve')?.addEventListener('click', async () => {
|
|
const res = await fetch(`/api/guestbook/${id}`, { method: 'PATCH' });
|
|
if (res.ok) li.remove();
|
|
});
|
|
|
|
li.querySelector('.reject')?.addEventListener('click', async () => {
|
|
const res = await fetch(`/api/guestbook/${id}`, { method: 'DELETE' });
|
|
if (res.ok) li.remove();
|
|
});
|
|
});
|
|
</script>
|
|
</Layout>
|