import { asc, inArray, sql } from "drizzle-orm"; import { redirect } from "next/navigation"; import { getTranslations } from "next-intl/server"; import { StatusCard } from "@/components/admin/dashboard"; import { db, NavigatorFlatcats, NavigatorPubliccats, queryRows, Rooms, } from "@/lib/db"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; // navigator_flatcats โ€” emulator-owned flat (private-room) categories shown in the // navigator. type Flatcat = { id: number; caption: string; captionSave: string; minRank: number; maxUserCount: number; canTrade: string; public: string; listType: number; orderNum: number; }; // navigator_publics โ€” keyless table, read via raw SQL. type PublicRow = { public_cat_id: number; room_id: number; visible: string; }; function YesNo({ on }: { on: boolean }) { return ( {on ? "Yes" : "No"} ); } export default async function AdminNavigation() { const { session, permissions } = await getAdminContext(); if (!canAccess(permissions, PERMS.PAGES_VIEW, session.user.rank)) { redirect("/admin"); } const t = await getTranslations("pages.admin.navigation"); let flatcats: Flatcat[] = []; try { flatcats = await db .select({ id: NavigatorFlatcats.id, caption: NavigatorFlatcats.caption, captionSave: NavigatorFlatcats.captionSave, minRank: NavigatorFlatcats.minRank, maxUserCount: NavigatorFlatcats.maxUserCount, canTrade: NavigatorFlatcats.canTrade, public: NavigatorFlatcats.public, listType: NavigatorFlatcats.listType, orderNum: NavigatorFlatcats.orderNum, }) .from(NavigatorFlatcats) .orderBy(asc(NavigatorFlatcats.orderNum), asc(NavigatorFlatcats.id)); } catch { flatcats = []; } let publics: PublicRow[] = []; try { publics = await queryRows(sql` SELECT public_cat_id, room_id, visible FROM navigator_publics ORDER BY public_cat_id ASC, room_id ASC `); } catch { publics = []; } const catIds = Array.from(new Set(publics.map((p) => p.public_cat_id))); const roomIds = Array.from(new Set(publics.map((p) => p.room_id))); let catNameById = new Map(); if (catIds.length) { try { const cats = await db .select({ id: NavigatorPubliccats.id, name: NavigatorPubliccats.name }) .from(NavigatorPubliccats) .where(inArray(NavigatorPubliccats.id, catIds)); catNameById = new Map(cats.map((c) => [c.id, c.name])); } catch { catNameById = new Map(); } } let roomNameById = new Map(); if (roomIds.length) { try { const rooms = await db .select({ id: Rooms.id, name: Rooms.name }) .from(Rooms) .where(inArray(Rooms.id, roomIds)); roomNameById = new Map(rooms.map((r) => [r.id, r.name])); } catch { roomNameById = new Map(); } } const publicFlatcats = flatcats.filter((c) => c.public === "1").length; const visiblePublics = publics.filter((p) => p.visible === "1").length; return (
0 ? "ok" : "neutral"} icon="๐Ÿ‘๏ธ" />

{t("flatCategories")}

navigator_flatcats ยท {flatcats.length} {t("rows")}

{flatcats.length === 0 ? (
{t("noCategories")}
) : (
{flatcats.map((c) => ( ))}
{t("colId")} Caption Caption (save) Min rank Max users Can trade Public List type {t("colOrder")}
{c.id} {c.caption || "โ€”"} {c.captionSave || "โ€”"} {c.minRank} {c.maxUserCount} {c.listType} {c.orderNum}
)}

{t("publicRooms")}

navigator_publics ยท {publics.length} {t("rows")}

{publics.length === 0 ? (
{t("noPublicRooms")}
) : (
{publics.map((p) => ( ))}
Public cat {t("colName")} Visible
{catNameById.get(p.public_cat_id) ?? "โ€”"}{" "} #{p.public_cat_id} {roomNameById.get(p.room_id) || t("unnamed")}{" "} #{p.room_id}
)}
); }