- Add organizer model/API, admin and public organizer pages, meetup cards - Refresh events/home/contact; add calendar dialog and carousel components - Optional Plausible via NEXT_PUBLIC_PLAUSIBLE_* env vars in root layout - Prisma migration, seed updates, baseline-and-migrate script Made-with: Cursor
43 lines
1.2 KiB
TypeScript
43 lines
1.2 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { notFound } from "next/navigation";
|
|
import OrganizerEventsClient from "./OrganizerEventsClient";
|
|
import { apiUrl } from "@/lib/api-base";
|
|
|
|
async function fetchOrganizer(slug: string) {
|
|
try {
|
|
const res = await fetch(apiUrl(`/organizers/by-slug/${encodeURIComponent(slug)}`), {
|
|
next: { revalidate: 300 },
|
|
});
|
|
if (!res.ok) return null;
|
|
return res.json() as Promise<{ id: string; name: string; slug: string }>;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
interface Props {
|
|
params: Promise<{ slug: string }>;
|
|
}
|
|
|
|
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|
const { slug } = await params;
|
|
const org = await fetchOrganizer(slug);
|
|
if (!org) {
|
|
return { title: "Organizer not found" };
|
|
}
|
|
return {
|
|
title: `Events by ${org.name}`,
|
|
description: `Upcoming and past Bitcoin events organized by ${org.name} in Belgium.`,
|
|
alternates: { canonical: `/events/organizer/${slug}` },
|
|
};
|
|
}
|
|
|
|
export default async function OrganizerArchivePage({ params }: Props) {
|
|
const { slug } = await params;
|
|
const org = await fetchOrganizer(slug);
|
|
if (!org) {
|
|
notFound();
|
|
}
|
|
return <OrganizerEventsClient slug={slug} organizerName={org.name} />;
|
|
}
|