Introduces the Go photo-api service, nginx/systemd deploy wiring, and Next.js gallery/lightbox pages so event photos can be managed and browsed. Co-authored-by: Cursor <cursoragent@cursor.com>
51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import type { Metadata } from 'next';
|
||
import { Suspense } from 'react';
|
||
import type { PhotoGallery, Photo } from '@/lib/api';
|
||
import GalleryClient from '@/app/(public)/photos/[slug]/GalleryClient';
|
||
|
||
const photoApiUrl = process.env.PHOTO_API_URL || 'http://localhost:3003';
|
||
|
||
interface PageProps {
|
||
params: { id: string }; // event slug, same param name as the parent route
|
||
}
|
||
|
||
// Public event galleries render server-side; link/ticket galleries return
|
||
// null here and are fetched client-side with the viewer's token.
|
||
async function getEventGallery(
|
||
eventSlug: string
|
||
): Promise<{ gallery: PhotoGallery; photos: Photo[] } | null> {
|
||
try {
|
||
const res = await fetch(
|
||
`${photoApiUrl}/api/photos/public/events/${encodeURIComponent(eventSlug)}/gallery`,
|
||
{ next: { revalidate: 300 } }
|
||
);
|
||
if (!res.ok) return null;
|
||
return await res.json();
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
||
const data = await getEventGallery(params.id);
|
||
if (!data) {
|
||
return { title: 'Event Photos', robots: { index: false } };
|
||
}
|
||
return {
|
||
title: `${data.gallery.title} – Photos`,
|
||
description:
|
||
data.gallery.description ||
|
||
`Photos from ${data.gallery.title}, a Spanglish language exchange event in Asunción.`,
|
||
};
|
||
}
|
||
|
||
export default async function EventGalleryPage({ params }: PageProps) {
|
||
const initial = await getEventGallery(params.id);
|
||
return (
|
||
// Suspense boundary required by useSearchParams() in the client child.
|
||
<Suspense>
|
||
<GalleryClient eventSlug={params.id} initial={initial} />
|
||
</Suspense>
|
||
);
|
||
}
|