91 lines
3 KiB
TypeScript
91 lines
3 KiB
TypeScript
|
|
import dynamicImport from "next/dynamic";
|
||
|
|
import { notFound } from "next/navigation";
|
||
|
|
import FacilitySearch from "@/app/FacilitySearch";
|
||
|
|
import {
|
||
|
|
type FacilityRecord,
|
||
|
|
enrichFacilities,
|
||
|
|
filterFacilitiesByArea,
|
||
|
|
getAvailablePlaceConfigs,
|
||
|
|
getPlaceConfigFromSlug,
|
||
|
|
} from "@/app/facilityData";
|
||
|
|
import { API_URL } from "@/config/constants";
|
||
|
|
|
||
|
|
const PlaceMap = dynamicImport(() => import("@/components/PlaceMap"), {
|
||
|
|
ssr: false,
|
||
|
|
loading: () => (
|
||
|
|
<div className="overflow-hidden rounded-[2rem] border border-[#D7DED0] bg-white p-8 shadow-sm">
|
||
|
|
<p className="text-sm text-[#617063]">Laster kartet...</p>
|
||
|
|
</div>
|
||
|
|
),
|
||
|
|
});
|
||
|
|
|
||
|
|
export const dynamicParams = true;
|
||
|
|
export const dynamic = "force-dynamic";
|
||
|
|
|
||
|
|
export async function generateStaticParams() {
|
||
|
|
return getAvailablePlaceConfigs().map((slug) => ({ 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 facilitiesInPlace = filterFacilitiesByArea(enrichFacilities(safeData), place.areaFilter);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<main className="site-shell min-h-screen">
|
||
|
|
<section className="mx-auto max-w-[1400px] px-4 py-8 sm:px-6 sm:py-10 lg:px-8 lg:py-12">
|
||
|
|
<div className="max-w-4xl">
|
||
|
|
<p className="mb-3 text-[11px] font-extrabold uppercase tracking-[0.3em] text-[#6FA786]">Steder</p>
|
||
|
|
<h1 className="section-title text-4xl text-[#112015] sm:text-5xl lg:text-6xl">{place.title}</h1>
|
||
|
|
<p className="mt-4 max-w-3xl text-base leading-8 text-[#617063]">{place.intro}</p>
|
||
|
|
<div className="mt-5 flex flex-wrap gap-3">
|
||
|
|
<span className="rounded-full bg-white px-4 py-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-[#112015] shadow-sm">
|
||
|
|
{facilitiesInPlace.length} anlegg
|
||
|
|
</span>
|
||
|
|
<span className="rounded-full bg-[#25312A] px-4 py-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-white">
|
||
|
|
Kart og liste i samme visning
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="mt-8">
|
||
|
|
<PlaceMap facilities={facilitiesInPlace} placeLabel={place.label} />
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<FacilitySearch
|
||
|
|
initialFacilities={safeData}
|
||
|
|
variant="catalog"
|
||
|
|
title={place.title}
|
||
|
|
intro={`Filtrer anleggene i ${place.label} videre etter banestatus, antall hull og andre egenskaper.`}
|
||
|
|
fixedAreaFilter={place.areaFilter}
|
||
|
|
hideTitleBlock
|
||
|
|
/>
|
||
|
|
</main>
|
||
|
|
);
|
||
|
|
}
|