Files
soroushasadi/app/(admin)/admin/page.tsx
T
soroush.asadi add78d8460
ci / build (push) Failing after 23s
deploy / deploy (push) Failing after 10m12s
first commit
2026-05-31 12:47:02 +03:30

96 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from 'next/link';
import { AdminShell } from '@/components/admin/AdminShell';
import { EDITABLE_SECTIONS } from '@/lib/content/sections';
import { sectionStatus } from '@/lib/db/store';
import { passwordConfigured } from '@/lib/auth/session';
export const dynamic = 'force-dynamic';
function timeAgo(ts: number): string {
const s = Math.floor((Date.now() - ts) / 1000);
if (s < 60) return 'just now';
const m = Math.floor(s / 60);
if (m < 60) return `${m}m ago`;
const h = Math.floor(m / 60);
if (h < 24) return `${h}h ago`;
return `${Math.floor(h / 24)}d ago`;
}
export default function AdminDashboard() {
const status = sectionStatus();
const usingDefaultPassword = !process.env.ADMIN_PASSWORD && passwordConfigured();
const edited = Object.keys(status).length;
return (
<AdminShell>
<div className="mx-auto max-w-4xl">
<div className="mb-8">
<h1 className="text-2xl font-bold text-white">Dashboard</h1>
<p className="mt-1 text-sm text-slate-400">
Edit every section of the site. {edited > 0 ? `${edited} section${edited > 1 ? 's' : ''} customized.` : 'All sections are at their defaults.'}
</p>
</div>
{usingDefaultPassword && (
<div className="mb-6 rounded-xl border border-magenta/30 bg-magenta/5 p-4 text-sm text-magenta">
<strong>Heads up:</strong> no <code className="font-mono">ADMIN_PASSWORD</code> is set, so the dev default
(<code className="font-mono">admin</code>) is in use. Set one in your environment before going live.
</div>
)}
<div className="grid gap-3 sm:grid-cols-2">
{EDITABLE_SECTIONS.map((s) => {
const edited = status[s.key];
return (
<Link
key={s.key}
href={`/admin/sections/${s.key}`}
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-center justify-between">
<h2 className="font-semibold text-white group-hover:text-electric">
{s.label.en}
<span className="ms-2 font-fa text-sm font-normal text-slate-500">
{s.label.fa}
</span>
</h2>
{edited ? (
<span className="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 · {timeAgo(edited)}
</span>
) : (
<span className="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>
<p className="mt-2 text-sm text-slate-400">{s.desc.en}</p>
</Link>
);
})}
</div>
<div className="mt-3 grid gap-3 sm:grid-cols-2">
<Link
href="/admin/posts"
className="group rounded-xl border border-violet/20 bg-violet/[0.03] p-5 transition-colors hover:border-violet/40 hover:bg-violet/[0.06]"
>
<div className="flex items-center justify-between">
<h2 className="font-semibold text-white group-hover:text-violet">
Journal articles
<span className="ms-2 font-fa text-sm font-normal text-slate-500">مقالات</span>
</h2>
<span className="font-mono text-[0.65rem] uppercase tracking-wider text-violet">
bodies
</span>
</div>
<p className="mt-2 text-sm text-slate-400">
Edit the full bilingual body of each blog post (lead + content blocks).
</p>
</Link>
</div>
</div>
</AdminShell>
);
}