75 lines
3.0 KiB
TypeScript
75 lines
3.0 KiB
TypeScript
import Link from 'next/link';
|
|
import { AdminShell } from '@/components/admin/AdminShell';
|
|
import { loadContent } from '@/lib/content/load';
|
|
import { loadAllPosts, loadPostOverrides } from '@/lib/content/posts-store';
|
|
|
|
// Always reflect live DB state in the editor list.
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
export default function AdminPostsPage() {
|
|
const posts = loadAllPosts();
|
|
const overrides = loadPostOverrides();
|
|
const { en } = loadContent();
|
|
const cardBySlug = new Map<string, (typeof en.blog.items)[number]>(
|
|
en.blog.items.map((p) => [p.slug, p]),
|
|
);
|
|
const slugs = Object.keys(posts);
|
|
const editedCount = Object.keys(overrides).length;
|
|
|
|
return (
|
|
<AdminShell>
|
|
<div className="mx-auto max-w-4xl">
|
|
<div className="mb-8">
|
|
<h1 className="text-2xl font-bold text-white">Journal articles</h1>
|
|
<p className="mt-1 text-sm text-slate-400">
|
|
Edit the full bilingual body of each post.{' '}
|
|
{editedCount > 0
|
|
? `${editedCount} article${editedCount > 1 ? 's' : ''} customized.`
|
|
: 'All articles are at their defaults.'}{' '}
|
|
Titles, excerpts and read time live under the{' '}
|
|
<Link href="/admin/sections/blog" className="text-electric hover:underline">
|
|
Journal
|
|
</Link>{' '}
|
|
section.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
{slugs.map((slug) => {
|
|
const card = cardBySlug.get(slug);
|
|
const post = posts[slug];
|
|
const edited = slug in overrides;
|
|
return (
|
|
<Link
|
|
key={slug}
|
|
href={`/admin/posts/${slug}`}
|
|
className="group rounded-xl border border-white/8 bg-white/[0.02] p-5 transition-colors hover:border-electric/30 hover:bg-electric/[0.03]"
|
|
>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<h2 className="font-semibold leading-snug text-white group-hover:text-electric">
|
|
{card?.title ?? slug}
|
|
</h2>
|
|
{edited ? (
|
|
<span className="shrink-0 rounded-full border border-emerald/30 bg-emerald/5 px-2 py-0.5 font-mono text-[0.6rem] uppercase tracking-wider text-emerald">
|
|
edited
|
|
</span>
|
|
) : (
|
|
<span className="shrink-0 rounded-full border border-white/10 px-2 py-0.5 font-mono text-[0.6rem] uppercase tracking-wider text-slate-500">
|
|
default
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="mt-2 flex items-center gap-3 font-mono text-[0.65rem] uppercase tracking-wider text-slate-500">
|
|
<span>{card?.category ?? '—'}</span>
|
|
<span>·</span>
|
|
<span>{post.date}</span>
|
|
</div>
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</AdminShell>
|
|
);
|
|
}
|