first commit
Made-with: Cursor
This commit is contained in:
86
frontend/app/events/[id]/page.tsx
Normal file
86
frontend/app/events/[id]/page.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { Metadata } from "next";
|
||||
import EventDetailClient from "./EventDetailClient";
|
||||
import { EventJsonLd, BreadcrumbJsonLd } from "@/components/public/JsonLd";
|
||||
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000/api";
|
||||
|
||||
async function fetchEvent(id: string) {
|
||||
try {
|
||||
const res = await fetch(`${apiUrl}/meetups/${id}`, {
|
||||
next: { revalidate: 300 },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
return res.json();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
params: Promise<{ id: string }>;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { id } = await params;
|
||||
const event = await fetchEvent(id);
|
||||
if (!event) {
|
||||
return { title: "Event Not Found" };
|
||||
}
|
||||
|
||||
const description =
|
||||
event.description?.slice(0, 160) ||
|
||||
`Bitcoin meetup: ${event.title}${event.location ? ` in ${event.location}` : ""}. Organized by the Belgian Bitcoin Embassy.`;
|
||||
|
||||
const ogImage = event.imageId
|
||||
? `/media/${event.imageId}`
|
||||
: `/og?title=${encodeURIComponent(event.title)}&type=event`;
|
||||
|
||||
return {
|
||||
title: event.title,
|
||||
description,
|
||||
openGraph: {
|
||||
type: "article",
|
||||
title: event.title,
|
||||
description,
|
||||
images: [{ url: ogImage, width: 1200, height: 630, alt: event.title }],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: event.title,
|
||||
description,
|
||||
images: [ogImage],
|
||||
},
|
||||
alternates: { canonical: `/events/${id}` },
|
||||
};
|
||||
}
|
||||
|
||||
export default async function EventDetailPage({ params }: Props) {
|
||||
const { id } = await params;
|
||||
const event = await fetchEvent(id);
|
||||
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://belgianbitcoinembassy.org";
|
||||
|
||||
return (
|
||||
<>
|
||||
{event && (
|
||||
<>
|
||||
<EventJsonLd
|
||||
name={event.title}
|
||||
description={event.description}
|
||||
startDate={event.date}
|
||||
location={event.location}
|
||||
url={`${siteUrl}/events/${id}`}
|
||||
imageUrl={event.imageId ? `${siteUrl}/media/${event.imageId}` : undefined}
|
||||
/>
|
||||
<BreadcrumbJsonLd
|
||||
items={[
|
||||
{ name: "Home", href: "/" },
|
||||
{ name: "Events", href: "/events" },
|
||||
{ name: event.title, href: `/events/${id}` },
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<EventDetailClient id={id} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user