import type { Metadata } from "next"; import { headers } from "next/headers"; import { qrLandings } from "@/components/landing"; import { LandingNotice } from "@/components/landing/shell"; import { prisma } from "@/lib/db"; import { ensureDefaultDomain, resolveRequestDomain } from "@/lib/domains"; import { getQrType } from "@/lib/qr/registry"; import { isValidSlug } from "@/lib/slug"; export const dynamic = "force-dynamic"; type PageProps = { params: Promise<{ slug: string }> }; /** * Öffentliche Landingpage eines dynamischen Codes. * * Hierher schickt `/r/[slug]` alle Typen, die keine fremde Adresse haben, * sondern eine Seite: Linksammlungen, hinterlegte Dateien, Feedback. * * Der Scan-Zähler wird bewusst **nicht** hier erhöht, sondern in `/r/[slug]`. * Sonst zählte jedes Neuladen dieser Seite als weiterer Scan. */ async function loadCode(slug: string) { if (!isValidSlug(slug)) return null; const matched = await resolveRequestDomain(await headers()); const domain = matched ?? { ...(await ensureDefaultDomain()), isActive: true }; if (!domain.isActive) return null; return prisma.qrCode.findUnique({ where: { domainId_slug: { domainId: domain.id, slug } }, }); } export async function generateMetadata({ params, }: PageProps): Promise { const { slug } = await params; const code = await loadCode(slug); const qrType = code ? getQrType(code.type) : undefined; if (!code || !qrType?.hasLandingPage) { return { title: "Nicht gefunden" }; } let title = qrType.title; try { title = qrType.summary(code.data); } catch { // Daten passen nicht mehr zum Schema — der Typname tut es auch. } // Absolut, damit der Titel nicht mit dem Anwendungsnamen ergänzt wird: // Wer hier landet, hat mit dem Generator nichts zu tun. return { title: { absolute: title } }; } export default async function LandingPage({ params }: PageProps) { const { slug } = await params; const code = await loadCode(slug); if (!code) { return ( Der Code wurde gelöscht oder hat nie existiert. Bitte wende dich an denjenigen, der ihn erstellt hat. ); } const qrType = getQrType(code.type); const Landing = qrType?.hasLandingPage ? qrLandings[qrType.id] : undefined; if (!qrType || !Landing) { return ( Dieser Code führt nicht auf eine Seite. Bitte wende dich an denjenigen, der ihn erstellt hat. ); } // Alte Datensätze können nach einer Schema-Änderung unbrauchbar sein. Das // ist kein Grund, den Besuchern einen Absturz zu zeigen. if (!qrType.validate(code.data).ok) { return ( Die hinterlegten Inhalte sind unvollständig. Bitte wende dich an denjenigen, der den Code erstellt hat. ); } return ( ); }