import type { Metadata } from "next"; import { notFound } from "next/navigation"; import PlaceExplorer from "@/app/sted/[slug]/PlaceExplorer"; import { buildPlaceAverageComparison, buildPlaceStats, buildPlaceStatsIntro, formatPlaceCount, formatPlaceCurrency, type FacilityRecord, enrichFacilities, filterFacilitiesByArea, getAvailablePlaceConfigs, getPlaceConfigFromSlug, getPlacePreposition, } from "@/app/facilityData"; import { API_URL } from "@/config/constants"; import { createBreadcrumbJsonLd, createCollectionPageJsonLd, createItemListJsonLd, createPageMetadata, } from "@/app/seo"; export const dynamicParams = true; export const dynamic = "force-dynamic"; export async function generateStaticParams() { return getAvailablePlaceConfigs().map((slug) => ({ slug })); } export async function generateMetadata({ params, }: { params: Promise<{ slug: string }>; }): Promise { const { slug } = await params; const place = getPlaceConfigFromSlug(slug); if (!place) { return createPageMetadata({ title: "Sted ikke funnet", description: "Denne stedssiden finnes ikke på TeeOff.", path: `/sted/${slug}`, }); } return createPageMetadata({ title: place.title, description: `${place.intro} TeeOff samler golfbaner i ${place.label} med oppdatert banestatus og baneprofiler.`, path: `/sted/${slug}`, }); } export default async function PlacePage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const place = getPlaceConfigFromSlug(slug); if (!place) { notFound(); } let facilities: FacilityRecord[] = []; try { const res = await fetch(`${API_URL}/facilities`, { next: { revalidate: 0 }, cache: "no-store", }); if (!res.ok) { throw new Error(`API returnerte status ${res.status}`); } facilities = await res.json(); } catch (error) { console.error("Kritisk feil ved henting av sted-data:", error); facilities = []; } const safeData = Array.isArray(facilities) ? facilities : []; const enrichedFacilities = enrichFacilities(safeData); const facilitiesInPlace = filterFacilitiesByArea(enrichedFacilities, place.areaFilter); const placeStats = buildPlaceStats(facilitiesInPlace); const nationalStats = buildPlaceStats(enrichedFacilities); const placeStatsIntro = buildPlaceStatsIntro(place.label, placeStats); const isNationalPlace = place.slug === "norge"; const placePreposition = isNationalPlace ? "i" : getPlacePreposition(place.label); const greenfeeComparison = isNationalPlace ? null : buildPlaceAverageComparison(placeStats.avgPrimetimeGreenfee, nationalStats.avgPrimetimeGreenfee); const membershipComparison = isNationalPlace ? null : buildPlaceAverageComparison(placeStats.avgStandardMembership, nationalStats.avgStandardMembership); const holeDistributionParts = [ `${formatPlaceCount(placeStats.par3HoleCount)} par 3-hull`, `${formatPlaceCount(placeStats.par4HoleCount)} par 4-hull`, `${formatPlaceCount(placeStats.par5HoleCount)} par 5-hull`, placeStats.par6HoleCount > 0 ? `${formatPlaceCount(placeStats.par6HoleCount)} par 6-hull` : null, ].filter((part): part is string => Boolean(part)); const holeDistributionText = holeDistributionParts.length > 1 ? `${holeDistributionParts.slice(0, -1).join(", ")} og ${holeDistributionParts.at(-1)}` : holeDistributionParts[0] ?? null; const shortestLongestText = placeStats.shortestHoleMeters !== null && placeStats.longestHoleMeters !== null ? `Det korteste golfhullet ${placePreposition} ${place.label} er ${placeStats.shortestHoleMeters} meter, mens det lengste er ${placeStats.longestHoleMeters} meter.` : null; const collectionJsonLd = createCollectionPageJsonLd({ name: place.title, description: place.intro, path: `/sted/${slug}`, }); const itemListJsonLd = createItemListJsonLd({ name: place.title, path: `/sted/${slug}`, items: facilitiesInPlace .filter((facility) => facility?.slug && facility?.name) .map((facility) => ({ name: facility.name, path: `/golfbaner/${facility.slug}`, description: facility.description, })), }); const breadcrumbJsonLd = createBreadcrumbJsonLd([ { name: "Hjem", path: "/" }, { name: "Steder", path: "/sted/norge" }, { name: place.label, path: `/sted/${slug}` }, ]); return ( <>