feat: add auth-protected /draft/ index page
This commit is contained in:
parent
7eaa9c689a
commit
85471bc712
1 changed files with 71 additions and 0 deletions
71
apps/www/src/pages/draft/index.astro
Normal file
71
apps/www/src/pages/draft/index.astro
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
---
|
||||||
|
export const prerender = false;
|
||||||
|
|
||||||
|
import { getSession } from 'auth-astro/server';
|
||||||
|
import { getCollection } from 'astro:content';
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const posts = await getCollection('posts', ({ data }) => data.draft === true);
|
||||||
|
|
||||||
|
// Group by category (default: "posts")
|
||||||
|
const grouped = posts.reduce((acc, post) => {
|
||||||
|
const category = post.data.category ?? 'posts';
|
||||||
|
if (!acc[category]) acc[category] = [];
|
||||||
|
acc[category].push(post);
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, typeof posts>);
|
||||||
|
|
||||||
|
// Sort categories: "posts" first, then alphabetically
|
||||||
|
const sortedCategories = Object.keys(grouped).sort((a, b) => {
|
||||||
|
if (a === 'posts') return -1;
|
||||||
|
if (b === 'posts') return 1;
|
||||||
|
return a.localeCompare(b);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort posts within each category: pinned first, then by date descending
|
||||||
|
for (const category of sortedCategories) {
|
||||||
|
grouped[category].sort((a, b) => {
|
||||||
|
if (a.data.pinned && !b.data.pinned) return -1;
|
||||||
|
if (!a.data.pinned && b.data.pinned) return 1;
|
||||||
|
return b.data.date.getTime() - a.data.date.getTime();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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="drafts - lewis m.w.">
|
||||||
|
|
||||||
|
<p class="muted">logged in as {session.user?.name} <a href="/api/auth/signout">sign out</a></p>
|
||||||
|
|
||||||
|
{sortedCategories.length === 0 ? (
|
||||||
|
<p class="muted">no drafts</p>
|
||||||
|
) : (
|
||||||
|
sortedCategories.map(category => (
|
||||||
|
<details open>
|
||||||
|
<summary>{category}</summary>
|
||||||
|
<pre set:html={grouped[category].map(post => `<span class="muted">${formatDate(post.data.date)}</span> <a href="/draft/${post.id}">${post.data.title}</a>${post.data.pinned ? ' [pinned]' : ''}`).join('\n')} />
|
||||||
|
</details>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</Layout>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue