fix(public): distinguish unavailable data from empty results and missing pages
CI / check (push) Successful in 56s
CI / deploy (push) Successful in 1m30s
CI / publish-container (push) Successful in 44s

This commit is contained in:
Simo committed 2026-09-11 00:39:53 +02:00
1 parent db4acbb46e
commit 445ef13846
16 files changed
+608 -169

No files matched your search

+9 -5
View File
@@ -1,6 +1,7 @@
import { desc } from "drizzle-orm";
import type { Metadata } from "next";
import { getTranslations } from "next-intl/server";
import { PublicLoadError } from "@/components/public/load-error";
import {
type LightboxPhoto,
PhotoLightbox,
@@ -9,6 +10,7 @@ import { ContentCard, EmptyState } from "@/components/public/ui";
import { cached } from "@/lib/cache";
import { CameraWeb, db } from "@/lib/db";
import { formatDate } from "@/lib/format-date";
import { publicReadFailure } from "@/lib/services/public-read";
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("pages.photos");
@@ -34,18 +36,18 @@ type Photo = {
export default async function PhotosPage() {
const t = await getTranslations("pages.photos");
let photos: Photo[] = [];
let photos: Photo[] | null = [];
try {
photos = await cached("photos:grid", 60_000, async () =>
db.select().from(CameraWeb).orderBy(desc(CameraWeb.timestamp)).limit(48),
);
} catch {
photos = [];
} catch (error) {
photos = publicReadFailure("photos")(error);
}
// 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) => ({
const items: LightboxPhoto[] = (photos ?? []).map((p) => ({
id: String(p.id),
url: p.url,
alt: t("photoAlt", { id: p.userId }),
@@ -58,7 +60,9 @@ export default async function PhotosPage() {
<ContentCard icon="📸" title={t("title")} subtitle={t("subtitle")} />
<ContentCard padded={items.length === 0}>
{items.length === 0 ? (
{photos === null ? (
<PublicLoadError href="/photos" />
) : items.length === 0 ? (
<EmptyState icon="📸">{t("noPhotos")}</EmptyState>
) : (
<PhotoLightbox photos={items} />