Nye-TeeOff/frontend/src/app/turneringer/page.tsx
2026-04-19 09:49:47 +02:00

100 lines
4.2 KiB
TypeScript

import { notFound } from "next/navigation";
import CourseVisitGallery from "@/components/CourseVisitGallery";
import InfoPageShell from "@/components/InfoPageShell";
import { getOpinionArticleBySlug, type CourseVisitBodyBlock } from "@/content/courseVisits";
import {
createBreadcrumbJsonLd,
createCollectionPageJsonLd,
createPageMetadata,
} from "@/app/seo";
export const dynamic = "force-dynamic";
const articleSlug = "note-to-self-lenker-til-viktige-turneringer-i-golfbox";
const pageTitle = "Turneringer";
const pageIntro = "Her er alle turneringene vi ikke vet hvordan vi skal finne i Golfbox (og andre steder). God golfsesong!";
function renderBlock(block: CourseVisitBodyBlock, index: number) {
if (block.type !== "richText") {
return null;
}
return (
<section key={index} className="surface-card rounded-[2rem] p-6 sm:p-8">
{block.title ? (
<h2 className="text-3xl font-black text-[#112015] sm:text-4xl">{block.title}</h2>
) : null}
<div
className={`course-visit-richtext space-y-4 text-base leading-8 text-[#334238] [&_a]:font-black [&_a]:text-[#112015] [&_a]:underline [&_a]:underline-offset-4 [&_em]:italic [&_h2]:mt-12 [&_h2]:text-3xl [&_h2]:font-black [&_h2]:text-[#112015] [&_h3]:mt-10 [&_h3]:text-2xl [&_h3]:font-black [&_iframe]:mt-5 [&_iframe]:aspect-video [&_iframe]:w-full [&_iframe]:rounded-[1.5rem] [&_iframe]:border [&_iframe]:border-[#112015]/8 [&_iframe]:shadow-[0_12px_30px_rgba(17,32,21,0.08)] [&_img]:mt-5 [&_img]:w-full [&_img]:rounded-[1.5rem] [&_img]:border [&_img]:border-[#112015]/8 [&_img]:shadow-[0_12px_30px_rgba(17,32,21,0.08)] [&_li]:mt-2 [&_p]:mt-4 [&_table]:mt-6 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-[#112015]/10 [&_td]:px-3 [&_td]:py-2 [&_th]:border [&_th]:border-[#112015]/10 [&_th]:bg-[#F4F7EE] [&_th]:px-3 [&_th]:py-2 [&_th]:text-left [&_ul]:mt-4 [&_ul]:list-disc [&_ul]:pl-6 ${
block.title ? "mt-4" : ""
}`}
dangerouslySetInnerHTML={{ __html: block.html }}
/>
</section>
);
}
export async function generateMetadata() {
const article = await getOpinionArticleBySlug(articleSlug);
return createPageMetadata({
title: pageTitle,
description: article?.description || "Viktige turneringslenker i Golfbox samlet på TeeOff.",
path: "/turneringer",
image: article?.heroImages[0]?.src,
});
}
export default async function TournamentsPage() {
const article = await getOpinionArticleBySlug(articleSlug);
if (!article) {
notFound();
}
const collectionJsonLd = createCollectionPageJsonLd({
name: pageTitle,
description: article.description,
path: "/turneringer",
});
const breadcrumbJsonLd = createBreadcrumbJsonLd([
{ name: "Hjem", path: "/" },
{ name: "Turneringer", path: "/turneringer" },
]);
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(collectionJsonLd) }}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
/>
<InfoPageShell eyebrow="Turneringer" title={article.title} intro={pageIntro}>
<div className="space-y-6">
<CourseVisitGallery title={article.title} media={article.mediaGallery.slice(0, 1)} />
{article.blocks.map((block, index) => renderBlock(block, index))}
{article.mediaGallery.length > 1 ? (
<section className="space-y-4">
<div className="flex items-end justify-between gap-4">
<div>
<p className="text-[11px] font-black uppercase tracking-[0.24em] text-[#8BC34A]">
Galleri
</p>
<h2 className="mt-3 text-3xl font-black text-[#112015] sm:text-4xl">
Bilder og video
</h2>
</div>
<p className="text-sm font-bold text-[#5A685C]">
{article.mediaGallery.length} elementer
</p>
</div>
<CourseVisitGallery title={article.title} media={article.mediaGallery} />
</section>
) : null}
</div>
</InfoPageShell>
</>
);
}