Files
anouma/app/(frontend)/aktuelles/[slug]/page.tsx
T

106 lines
3.4 KiB
TypeScript

import type { Metadata } from "next";
import { notFound, permanentRedirect, redirect } from "next/navigation";
import { PageHeader } from "@/components/PageHeader";
import { Section } from "@/components/Section";
import { ImagePlaceholder } from "@/components/ImagePlaceholder";
import { RichText } from "@/components/RichText";
import { getPostBySlug } from "@/lib/payload/content";
import { mediaAlt, mediaUrl } from "@/lib/payload/media";
import { getSEOSettingsGlobal } from "@/lib/payload/globals";
import { resolveSeo } from "@/lib/seo/resolve";
import { buildMetadata } from "@/lib/seo/metadata";
import { getSiteUrl } from "@/lib/seo/config";
import { excerptFromRichText } from "@/lib/seo/textExcerpt";
import { JsonLd, articleJsonLd } from "@/lib/seo/jsonld";
import { resolveRedirect } from "@/lib/seo/redirects";
import { siteConfig } from "@/lib/site";
export const dynamic = "force-dynamic";
type Args = { params: Promise<{ slug: string }> };
async function resolvePostOrRedirect(slug: string) {
const post = await getPostBySlug(slug);
if (post) return post;
const match = await resolveRedirect(`/aktuelles/${slug}`);
if (match) {
if (match.permanent) permanentRedirect(match.to);
redirect(match.to);
}
return null;
}
export async function generateMetadata({ params }: Args): Promise<Metadata> {
const { slug } = await params;
const [post, seoSettings] = await Promise.all([getPostBySlug(slug), getSEOSettingsGlobal()]);
if (!post) return {};
const resolved = resolveSeo({
seo: post.seo,
fallbackTitle: `${post.title} - ${siteConfig.name}`,
fallbackDescription: () => post.teaser,
fallbackImage: post.coverImage,
defaultOgImage: seoSettings.defaultOgImage,
});
return buildMetadata({
title: resolved.title,
description: resolved.description,
path: `/aktuelles/${post.slug}`,
ogImageUrl: resolved.ogImageUrl,
keywords: resolved.keywords,
type: "article",
});
}
export default async function PostDetailPage({ params }: Args) {
const { slug } = await params;
const post = await resolvePostOrRedirect(slug);
if (!post) notFound();
const publishDate = new Date(post.publishDate ?? post.createdAt).toLocaleDateString("de-DE", {
day: "2-digit",
month: "long",
year: "numeric",
});
const siteUrl = await getSiteUrl();
return (
<>
<JsonLd
data={articleJsonLd({
post,
description: post.seo?.description || post.teaser || excerptFromRichText(post.content),
imageUrl: mediaUrl(post.coverImage, "hero"),
siteUrl,
providerName: siteConfig.name,
})}
/>
<PageHeader
eyebrow={publishDate}
title={post.title}
lead={post.teaser}
crumbs={[{ title: "Aktuelles", href: "/aktuelles" }, { title: post.title }]}
/>
<div className="mx-auto -mt-10 max-w-5xl px-6 sm:px-8 lg:px-12">
<div className="relative aspect-[21/9] w-full">
<ImagePlaceholder
mood="sand"
label={post.title}
src={mediaUrl(post.coverImage, "hero")}
alt={mediaAlt(post.coverImage) ?? post.title}
shape="soft"
priority
className="h-full w-full"
/>
</div>
</div>
<Section tone="plain">
<div className="mx-auto max-w-2xl">
<RichText data={post.content} />
</div>
</Section>
</>
);
}