kennzeichen-seite/frontend/app/page.tsx

135 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export const dynamic = 'force-dynamic';
import { unstable_noStore as noStore } from 'next/cache';
import Link from "next/link";
import { pb, COUNTRY_LABELS, COUNTRY_FLAGS } from "@/lib/pb";
async function getStats() {
noStore();
try {
const [kz, diplo, gesehen] = await Promise.all([
pb.collection("kennzeichen").getList(1, 1, { filter: "active=true" }),
pb.collection("diplomatenkennzeichen").getList(1, 1),
pb.collection("gesehen").getList(1, 1),
]);
return {
kennzeichen: kz.totalItems,
diplomaten: diplo.totalItems,
gesehen: gesehen.totalItems,
};
} catch {
return { kennzeichen: 0, diplomaten: 0, gesehen: 0 };
}
}
async function getLasteSeen() {
noStore();
try {
return pb.collection("gesehen").getList(1, 5, { sort: "-datum" });
} catch {
return null;
}
}
export default async function Home() {
const [stats, latest] = await Promise.all([getStats(), getLasteSeen()]);
const countries = Object.entries(COUNTRY_LABELS).slice(0, 12);
return (
<div className="max-w-6xl mx-auto px-6 py-16">
{/* Hero */}
<div className="mb-20">
<div className="inline-block mb-6 px-3 py-1 border border-[var(--accent)] rounded-sm text-[var(--accent)] text-xs font-mono tracking-widest uppercase">
Open Data · Eigensammlung
</div>
<h1 style={{ fontFamily: "'Syne', sans-serif", fontWeight: 800, fontSize: "clamp(2.5rem, 6vw, 4.5rem)", lineHeight: 1.05, letterSpacing: "-0.03em" }}
className="text-[var(--ink)] mb-6 max-w-3xl">
Kennzeichen.<br />Gesammelt, dokumentiert,<br />
<span className="text-[var(--accent)]">geteilt.</span>
</h1>
<p className="text-[var(--muted)] text-lg max-w-xl leading-relaxed">
Persönliche Datenbank europäischer Kfz-Kennzeichen mit Sonderformen,
Diplomatenkennzeichen und allem was sich nicht einfach einordnen lässt.
</p>
<div className="flex gap-3 mt-8">
<Link href="/kennzeichen"
className="px-5 py-2.5 bg-[var(--ink)] text-[var(--paper)] rounded-md text-sm font-medium hover:bg-[var(--accent)] transition-colors"
style={{ fontFamily: "'Syne', sans-serif" }}>
Datenbank
</Link>
<Link href="/blog"
className="px-5 py-2.5 border border-[var(--warm)] text-[var(--ink)] rounded-md text-sm font-medium hover:border-[var(--ink)] transition-colors"
style={{ fontFamily: "'Syne', sans-serif" }}>
Blog lesen
</Link>
</div>
</div>
{/* Stats */}
<div className="grid grid-cols-3 gap-4 mb-20">
{[
{ label: "Kennzeichen", value: stats.kennzeichen.toLocaleString("de") },
{ label: "Diplomaten­kz.", value: stats.diplomaten.toLocaleString("de") },
{ label: "Gesehen", value: stats.gesehen.toLocaleString("de") },
].map((s) => (
<div key={s.label} className="border border-[var(--warm)] rounded-lg p-6 bg-white/40">
<div style={{ fontFamily: "'Syne', sans-serif", fontWeight: 700, fontSize: "2.25rem", lineHeight: 1 }}
className="text-[var(--ink)] mb-1">
{s.value}
</div>
<div className="text-sm text-[var(--muted)]">{s.label}</div>
</div>
))}
</div>
{/* Länder */}
<div className="mb-20">
<h2 style={{ fontFamily: "'Syne', sans-serif", fontWeight: 700, fontSize: "1.25rem" }}
className="mb-6 text-[var(--ink)]">
Länder in der Datenbank
</h2>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
{countries.map(([key, label]) => (
<Link key={key} href={`/kennzeichen?land=${key}`}
className="flex items-center gap-2.5 px-4 py-3 border border-[var(--warm)] rounded-lg bg-white/40 hover:border-[var(--ink)] hover:bg-white/80 transition-all text-sm">
<span className="text-xl">{COUNTRY_FLAGS[key] ?? "🌍"}</span>
<span>{label}</span>
</Link>
))}
<Link href="/kennzeichen"
className="flex items-center justify-center gap-2 px-4 py-3 border border-dashed border-[var(--warm)] rounded-lg text-sm text-[var(--muted)] hover:text-[var(--ink)] hover:border-[var(--ink)] transition-all">
Alle anzeigen
</Link>
</div>
</div>
{/* Zuletzt gesehen */}
{latest && latest.items.length > 0 && (
<div>
<h2 style={{ fontFamily: "'Syne', sans-serif", fontWeight: 700, fontSize: "1.25rem" }}
className="mb-6 text-[var(--ink)]">
Zuletzt gesehen
</h2>
<div className="space-y-2">
{latest.items.map((item: any) => (
<div key={item.id} className="flex items-center gap-4 px-4 py-3 border border-[var(--warm)] rounded-lg bg-white/40">
{item.kennzeichen_code && <span className="kz-badge seen">{item.kennzeichen_code}</span>}
<div className="flex-1">
<span className="text-sm font-medium">{item.kennzeichen_name || "—"}</span>
<span className="text-xs text-[var(--muted)] ml-2">{COUNTRY_FLAGS[item.land] ?? ""}</span>
</div>
<span className="text-xs text-[var(--muted)] font-mono">
{new Date(item.datum).toLocaleDateString("de-DE")}
</span>
</div>
))}
</div>
<Link href="/sammlung" className="inline-block mt-4 text-sm text-[var(--accent)] hover:underline">
Gesamte Sammlung
</Link>
</div>
)}
</div>
);
}