import { desc } from "drizzle-orm"; import type { Metadata } from "next"; import { getTranslations } from "next-intl/server"; import { type LightboxPhoto, PhotoLightbox, } from "@/components/public/photo-lightbox"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { cached } from "@/lib/cache"; import { CameraWeb, db } from "@/lib/db"; import { formatDate } from "@/lib/format-date"; export async function generateMetadata(): Promise { const t = await getTranslations("pages.photos"); return { title: t("title"), description: t("subtitle"), openGraph: { title: t("title"), description: t("subtitle"), type: "website", }, }; } type Photo = { id: number; userId: number; roomId: number; timestamp: number; url: string; }; export default async function PhotosPage() { const t = await getTranslations("pages.photos"); let photos: Photo[] = []; try { photos = await cached("photos:grid", 60_000, async () => db.select().from(CameraWeb).orderBy(desc(CameraWeb.timestamp)).limit(48), ); } catch { photos = []; } // Pre-shape for the client lightbox: translate captions server-side so the // client component stays free of i18n/db dependencies. const items: LightboxPhoto[] = photos.map((p) => ({ id: String(p.id), url: p.url, alt: t("photoAlt", { id: p.userId }), date: formatDate(new Date(p.timestamp * 1000)), user: t("byUser", { id: p.userId }), })); return (
{items.length === 0 ? ( {t("noPhotos")} ) : ( )}
); }