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

@@ -4,6 +4,7 @@ import { getTranslations } from "next-intl/server";
import type { CSSProperties } from "react";
import { replyToThread } from "@/actions/social";
import Link from "@/components/link";
import { PublicLoadError } from "@/components/public/load-error";
import { ContentCard, EmptyState } from "@/components/public/ui";
import { auth } from "@/lib/auth";
import {
@@ -14,6 +15,7 @@ import {
User,
} from "@/lib/db";
import { formatDate } from "@/lib/format-date";
import { publicReadFailure } from "@/lib/services/public-read";
type SearchParams = Promise<{ replied?: string; error?: string }>;
@@ -60,6 +62,8 @@ export default async function GuildForumThreadPage({
pinned: number | null;
openerId: number | null;
} | null = null;
let postsFailed = false;
let authorsFailed = false;
let posts: {
id: number;
userId: number;
@@ -96,9 +100,15 @@ export default async function GuildForumThreadPage({
]);
guild = guildRow;
thread = threadRow;
} catch {
guild = null;
thread = null;
} catch (error) {
publicReadFailure("guild.thread")(error);
return (
<main className="page-grid">
<ContentCard>
<PublicLoadError href={`/guilds/${guildId}/forum/${threadId}`} />
</ContentCard>
</main>
);
}
if (!guild || !thread) notFound();
@@ -122,7 +132,9 @@ export default async function GuildForumThreadPage({
asc(GuildsForumsComments.createdAt),
asc(GuildsForumsComments.id),
);
} catch {
} catch (error) {
publicReadFailure("guild.posts")(error);
postsFailed = true;
posts = [];
}
@@ -137,7 +149,9 @@ export default async function GuildForumThreadPage({
.from(User)
.where(inArray(User.id, authorIds))
: [];
} catch {
} catch (error) {
publicReadFailure("guild.post-authors")(error);
authorsFailed = true;
users = [];
}
const usernameById = new Map(users.map((u) => [u.id, u.username]));
@@ -195,10 +209,17 @@ export default async function GuildForumThreadPage({
<ContentCard
icon="📝"
title={t("postsTitle")}
subtitle={t("postsSubtitle", { count: posts.length })}
padded={posts.length === 0}
subtitle={
postsFailed ? undefined : t("postsSubtitle", { count: posts.length })
}
padded={posts.length === 0 || authorsFailed}
>
{posts.length === 0 ? (
{authorsFailed && (
<PublicLoadError href={`/guilds/${guild.id}/forum/${thread.id}`} />
)}
{postsFailed ? (
<PublicLoadError href={`/guilds/${guild.id}/forum/${thread.id}`} />
) : posts.length === 0 ? (
<EmptyState icon="📝">{t("postsEmpty")}</EmptyState>
) : (
<ul