Files
Epicnabbo-Catalogus-Updated…/src/app/(site)/staff/page.tsx
T
openhands 7a41775c7e fix: disable route prefetching app-wide to avoid spurious requests
Wrap next/link in a shared Link component that ships prefetch=false by
default, so no route is ever prefetched (viewport or hover) anymore, and
drop the DNS prefetch hint. Removes hidden background requests that were
the source of intermittent issues.
2026-08-29 19:27:13 +02:00

124 lines
3.0 KiB
TypeScript

import { asc, desc, eq, gte } from "drizzle-orm";
import { getTranslations } from "next-intl/server";
import Link from "@/components/link";
import { ContentCard, EmptyState } from "@/components/public/ui";
import { db, User, WebsiteTeams } from "@/lib/db";
import { siteSettings } from "@/lib/services/site-settings";
export const metadata = { title: "Staff" };
type StaffMember = {
username: string;
look: string;
rank: number;
motto: string;
};
type Team = {
id: string;
rankName: string;
badge: string | null;
jobDescription: string | null;
staffColor: string;
};
export default async function StaffPage() {
const t = await getTranslations("pages.staff");
const minStaffRank =
Number(await siteSettings.get("min_staff_rank", "7")) || 7;
// Independent queries — staff members and teams load concurrently.
const [staff, teams] = await Promise.all([
db
.select({
username: User.username,
look: User.look,
rank: User.rank,
motto: User.motto,
})
.from(User)
.where(gte(User.rank, minStaffRank))
.orderBy(desc(User.rank), asc(User.username))
.limit(100)
.catch((): StaffMember[] => []),
db
.select({
id: WebsiteTeams.id,
rankName: WebsiteTeams.rankName,
badge: WebsiteTeams.badge,
jobDescription: WebsiteTeams.jobDescription,
staffColor: WebsiteTeams.staffColor,
})
.from(WebsiteTeams)
.where(eq(WebsiteTeams.hiddenRank, false))
.orderBy(asc(WebsiteTeams.id))
.then((rows) => rows.map((row) => ({ ...row, id: String(row.id) })))
.catch((): Team[] => []),
]);
return (
<main style={{ display: "grid", gap: "1.5rem" }}>
<ContentCard icon="🛡️" title={t("title")} subtitle={t("subtitle")} />
{teams.length > 0 ? (
<ContentCard
icon="⭐"
title={t("ranksTitle")}
subtitle={t("ranksSubtitle")}
>
<div className="card-grid sm-2 lg-3">
{teams.map((team) => (
<div key={team.id} className="card">
<h3 style={{ margin: "0 0 0.25rem", color: team.staffColor }}>
{team.rankName}
</h3>
{team.jobDescription ? (
<p className="muted" style={{ margin: 0 }}>
{team.jobDescription}
</p>
) : null}
</div>
))}
</div>
</ContentCard>
) : null}
<ContentCard
icon="👥"
title={t("membersTitle")}
subtitle={
staff.length === 0
? t("membersEmptySubtitle")
: t("membersSubtitle", { count: staff.length })
}
padded={staff.length === 0}
>
{staff.length === 0 ? (
<EmptyState icon="🛡️">{t("emptyState")}</EmptyState>
) : (
<table>
<thead>
<tr>
<th>{t("colUsername")}</th>
<th>{t("colRank")}</th>
<th>{t("colMotto")}</th>
</tr>
</thead>
<tbody>
{staff.map((u) => (
<tr key={u.username}>
<td>
<Link href={`/u/${u.username}`}>{u.username}</Link>
</td>
<td>{u.rank}</td>
<td className="muted">{u.motto || "—"}</td>
</tr>
))}
</tbody>
</table>
)}
</ContentCard>
</main>
);
}