Før aleggsbilde-interface
This commit is contained in:
parent
8bfd351582
commit
5a1944b216
2 changed files with 78 additions and 9 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import { ImageResponse } from "next/og";
|
import { ImageResponse } from "next/og";
|
||||||
import { API_URL } from "@/config/constants";
|
import { API_URL } from "@/config/constants";
|
||||||
|
import { resolveFacilityAlias } from "@/app/facilityAliases";
|
||||||
import { buildAbsoluteUrl } from "@/app/seo";
|
import { buildAbsoluteUrl } from "@/app/seo";
|
||||||
|
|
||||||
export const size = {
|
export const size = {
|
||||||
|
|
@ -13,14 +14,44 @@ type OpenGraphImageProps = {
|
||||||
params: Promise<{ slug: string }>;
|
params: Promise<{ slug: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type OpenGraphFacility = {
|
||||||
|
name: string;
|
||||||
|
city?: string | null;
|
||||||
|
county?: string | null;
|
||||||
|
image_url?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
async function getFacility(slug: string) {
|
async function getFacility(slug: string) {
|
||||||
const res = await fetch(`${API_URL}/facilities/${slug}`, { cache: "no-store" });
|
const res = await fetch(`${API_URL}/facilities/${slug}`, { cache: "no-store" });
|
||||||
return res.json();
|
if (!res.ok) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const facility = (await res.json()) as Partial<OpenGraphFacility> | null;
|
||||||
|
if (!facility?.name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return facility as OpenGraphFacility;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getFacilityForSlug(slug: string) {
|
||||||
|
const facility = await getFacility(slug);
|
||||||
|
if (facility) {
|
||||||
|
return facility;
|
||||||
|
}
|
||||||
|
|
||||||
|
const canonicalSlug = await resolveFacilityAlias(slug);
|
||||||
|
if (!canonicalSlug || canonicalSlug === slug) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFacility(canonicalSlug);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function OpenGraphImage({ params }: OpenGraphImageProps) {
|
export default async function OpenGraphImage({ params }: OpenGraphImageProps) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const facility = await getFacility(slug);
|
const facility = await getFacilityForSlug(slug);
|
||||||
|
|
||||||
const title = facility?.name || "TeeOff";
|
const title = facility?.name || "TeeOff";
|
||||||
const location = [facility?.city, facility?.county].filter(Boolean).join(" · ") || "Norske golfbaner";
|
const location = [facility?.city, facility?.county].filter(Boolean).join(" · ") || "Norske golfbaner";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
import { notFound, permanentRedirect } from "next/navigation";
|
||||||
import { API_URL } from "@/config/constants";
|
import { API_URL } from "@/config/constants";
|
||||||
|
import { resolveFacilityAlias } from "@/app/facilityAliases";
|
||||||
|
import type { FacilityRecord } from "@/app/facilityData";
|
||||||
import {
|
import {
|
||||||
createBreadcrumbJsonLd,
|
createBreadcrumbJsonLd,
|
||||||
createFacilityJsonLd,
|
createFacilityJsonLd,
|
||||||
|
|
@ -13,17 +16,47 @@ type GolfCoursePageProps = {
|
||||||
params: Promise<{ slug: string }>;
|
params: Promise<{ slug: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type FacilityPageData = FacilityRecord & {
|
||||||
|
address?: string | null;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
async function getFacility(slug: string) {
|
async function getFacility(slug: string) {
|
||||||
const res = await fetch(`${API_URL}/facilities/${slug}`, { cache: "no-store" });
|
const res = await fetch(`${API_URL}/facilities/${slug}`, { cache: "no-store" });
|
||||||
return res.json();
|
if (!res.ok) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const facility = (await res.json()) as Partial<FacilityPageData> | null;
|
||||||
|
if (typeof facility?.id !== "number" || !facility?.name || !facility?.slug) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return facility as FacilityPageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCanonicalSlug(slug: string) {
|
||||||
|
const canonicalSlug = await resolveFacilityAlias(slug);
|
||||||
|
if (!canonicalSlug || canonicalSlug === slug) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canonicalSlug;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({ params }: GolfCoursePageProps): Promise<Metadata> {
|
export async function generateMetadata({ params }: GolfCoursePageProps): Promise<Metadata> {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const facility = await getFacility(slug);
|
let facility = await getFacility(slug);
|
||||||
if (!facility || facility.error) {
|
if (!facility) {
|
||||||
|
const canonicalSlug = await getCanonicalSlug(slug);
|
||||||
|
if (canonicalSlug) {
|
||||||
|
facility = await getFacility(canonicalSlug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!facility) {
|
||||||
return createPageMetadata({
|
return createPageMetadata({
|
||||||
title: "Golfbane ikke funnet",
|
title: "Golfbane ikke funnet",
|
||||||
description: "Golfbanen du prøvde å åpne finnes ikke på TeeOff.",
|
description: "Golfbanen du prøvde å åpne finnes ikke på TeeOff.",
|
||||||
|
|
@ -37,8 +70,8 @@ export async function generateMetadata({ params }: GolfCoursePageProps): Promise
|
||||||
return createPageMetadata({
|
return createPageMetadata({
|
||||||
title,
|
title,
|
||||||
description: trimDescription(facility.description) || fallbackDescription,
|
description: trimDescription(facility.description) || fallbackDescription,
|
||||||
path: `/golfbaner/${slug}`,
|
path: `/golfbaner/${facility.slug}`,
|
||||||
image: `/golfbaner/${slug}/opengraph-image`,
|
image: `/golfbaner/${facility.slug}/opengraph-image`,
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
return createPageMetadata({
|
return createPageMetadata({
|
||||||
|
|
@ -53,8 +86,13 @@ export default async function GolfCoursePage({ params }: GolfCoursePageProps) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const facility = await getFacility(slug);
|
const facility = await getFacility(slug);
|
||||||
|
|
||||||
if (!facility || facility.error) {
|
if (!facility) {
|
||||||
return <div className="p-20 text-center font-bold text-2xl">Fant ikke golfbanen...</div>;
|
const canonicalSlug = await getCanonicalSlug(slug);
|
||||||
|
if (canonicalSlug) {
|
||||||
|
permanentRedirect(`/golfbaner/${canonicalSlug}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
const facilityJsonLd = createFacilityJsonLd(facility);
|
const facilityJsonLd = createFacilityJsonLd(facility);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue