134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
|
|
import { ImageResponse } from "next/og";
|
||
|
|
import { API_URL } from "@/config/constants";
|
||
|
|
import { buildAbsoluteUrl } from "@/app/seo";
|
||
|
|
|
||
|
|
export const size = {
|
||
|
|
width: 1200,
|
||
|
|
height: 630,
|
||
|
|
};
|
||
|
|
|
||
|
|
export const contentType = "image/png";
|
||
|
|
|
||
|
|
type OpenGraphImageProps = {
|
||
|
|
params: Promise<{ slug: string }>;
|
||
|
|
};
|
||
|
|
|
||
|
|
async function getFacility(slug: string) {
|
||
|
|
const res = await fetch(`${API_URL}/facilities/${slug}`, { cache: "no-store" });
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
export default async function OpenGraphImage({ params }: OpenGraphImageProps) {
|
||
|
|
const { slug } = await params;
|
||
|
|
const facility = await getFacility(slug);
|
||
|
|
|
||
|
|
const title = facility?.name || "TeeOff";
|
||
|
|
const location = [facility?.city, facility?.county].filter(Boolean).join(" · ") || "Norske golfanlegg";
|
||
|
|
const imageUrl = facility?.image_url ? buildAbsoluteUrl(facility.image_url) : null;
|
||
|
|
|
||
|
|
return new ImageResponse(
|
||
|
|
(
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: "flex",
|
||
|
|
position: "relative",
|
||
|
|
width: "100%",
|
||
|
|
height: "100%",
|
||
|
|
overflow: "hidden",
|
||
|
|
background: "linear-gradient(135deg, #1f2b24 0%, #3b4a3f 100%)",
|
||
|
|
color: "white",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{imageUrl ? (
|
||
|
|
<img
|
||
|
|
src={imageUrl}
|
||
|
|
alt={title}
|
||
|
|
width={1200}
|
||
|
|
height={630}
|
||
|
|
style={{
|
||
|
|
position: "absolute",
|
||
|
|
inset: 0,
|
||
|
|
width: "100%",
|
||
|
|
height: "100%",
|
||
|
|
objectFit: "cover",
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
) : null}
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
position: "absolute",
|
||
|
|
inset: 0,
|
||
|
|
background:
|
||
|
|
"linear-gradient(180deg, rgba(17,32,21,0.15) 0%, rgba(17,32,21,0.82) 72%, rgba(17,32,21,0.92) 100%)",
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
position: "relative",
|
||
|
|
display: "flex",
|
||
|
|
flexDirection: "column",
|
||
|
|
justifyContent: "space-between",
|
||
|
|
width: "100%",
|
||
|
|
height: "100%",
|
||
|
|
padding: "52px 58px",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: "inline-flex",
|
||
|
|
alignSelf: "flex-start",
|
||
|
|
borderRadius: 999,
|
||
|
|
background: "rgba(139, 195, 74, 0.92)",
|
||
|
|
color: "#112015",
|
||
|
|
padding: "12px 22px",
|
||
|
|
fontSize: 22,
|
||
|
|
fontWeight: 800,
|
||
|
|
letterSpacing: "0.18em",
|
||
|
|
textTransform: "uppercase",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
TeeOff
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 18, maxWidth: 900 }}>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: "flex",
|
||
|
|
fontSize: 28,
|
||
|
|
fontWeight: 700,
|
||
|
|
letterSpacing: "0.08em",
|
||
|
|
textTransform: "uppercase",
|
||
|
|
color: "#9ecb66",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
Golfbane
|
||
|
|
</div>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: "flex",
|
||
|
|
fontSize: 66,
|
||
|
|
lineHeight: 1.02,
|
||
|
|
fontWeight: 900,
|
||
|
|
letterSpacing: "-0.04em",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{title}
|
||
|
|
</div>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: "flex",
|
||
|
|
fontSize: 30,
|
||
|
|
fontWeight: 600,
|
||
|
|
color: "rgba(255,255,255,0.88)",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{location}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
),
|
||
|
|
size,
|
||
|
|
);
|
||
|
|
}
|