import { redirect } from "next/navigation"; import type { ReactNode } from "react"; import { getTranslations } from "next-intl/server"; import { AdminNavLink } from "@/components/admin/admin-nav-link"; import { requireStaff } from "@/lib/admin/guard"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; import { LayoutDashboard, Newspaper, Tags, Compass, HelpCircle, Megaphone, SquarePen, Image, Users, Ban, Globe, Shield, ClipboardList, Group, Key, Store, ShoppingCart, Receipt, Ticket, CreditCard, Gem, Award, Trophy, Calendar, Radio, History, Terminal, Monitor, Bell, FileText, Filter, Wrench, Settings, DoorOpen, Mail, Palette, Cog, LogOut, } from "lucide-react"; export const dynamic = "force-dynamic"; function getNavGroups(t: (key: string) => string) { return [ { label: t("overview"), icon: , items: [{ href: "/admin", label: t("dashboard"), icon: }], }, { label: t("content"), icon: , items: [ { href: "/admin/articles", label: t("articles"), icon: }, { href: "/admin/tags", label: t("tags"), icon: }, { href: "/admin/navigation", label: t("navigator"), icon: }, { href: "/admin/help-questions", label: t("helpCenter"), icon: }, { href: "/admin/ads", label: t("advertisements"), icon: }, { href: "/admin/writeable-boxes", label: t("writeableBoxes"), icon: }, { href: "/admin/photos", label: t("photos"), icon: }, ], }, { label: t("usersAccess"), icon: , items: [ { href: "/admin/users", label: t("users"), icon: }, { href: "/admin/bans", label: t("bans"), icon: }, { href: "/admin/ip", label: t("ipManagement"), icon: }, { href: "/admin/vpn", label: t("vpn"), icon: }, { href: "/admin/applications", label: t("applications"), icon: }, { href: "/admin/teams", label: t("teams"), icon: }, { href: "/admin/permissions", label: t("permissions"), icon: }, ], }, { label: t("economy"), icon: , items: [ { href: "/admin/catalog", label: t("catalog"), icon: }, { href: "/admin/shop", label: t("shop"), icon: }, { href: "/admin/transactions", label: t("transactions"), icon: }, { href: "/admin/vouchers", label: t("vouchers"), icon: }, { href: "/admin/subscriptions", label: t("subscriptions"), icon: }, { href: "/admin/rare-values", label: t("rareValues"), icon: }, { href: "/admin/badges", label: t("badges"), icon: }, { href: "/admin/achievements", label: t("achievements"), icon: }, { href: "/admin/calendar", label: t("calendar"), icon: }, ], }, { label: t("radio"), icon: , items: [ { href: "/admin/radio", label: t("radio"), icon: }, { href: "/admin/radio/history", label: t("radioHistory"), icon: }, ], }, { label: t("system"), icon: , items: [ { href: "/admin/commandocentrum", label: t("commandocentrum"), icon: }, { href: "/admin/emulator", label: t("emulator"), icon: }, { href: "/admin/alerts", label: t("alerts"), icon: }, { href: "/admin/logs", label: t("logs"), icon: }, { href: "/admin/wordfilter", label: t("wordFilter"), icon: }, { href: "/admin/maintenance", label: t("maintenance"), icon: }, { href: "/admin/housekeeping", label: t("housekeeping"), icon: }, { href: "/admin/rooms", label: t("rooms"), icon: }, { href: "/admin/email-templates", label: t("emailTemplates"), icon: }, { href: "/admin/theme", label: t("theme"), icon: }, { href: "/admin/media", label: t("media"), icon: }, { href: "/admin/favicon", label: t("favicon"), icon: }, { href: "/admin/settings", label: t("settings"), icon: }, ], }, ]; } export default async function AdminLayout({ children }: { children: ReactNode }) { const staff = await requireStaff(); const t = await getTranslations("pages.admin.nav"); const navGroups = getNavGroups(t); if (await siteSettings.getBool("force_staff_2fa", false)) { const u = await prisma.user .findUnique({ where: { id: staff.id }, select: { twoFactorConfirmedAt: true } }) .catch(() => null); if (!u?.twoFactorConfirmedAt) redirect("/settings/2fa?error=staffrequired"); } return (
{children}
); } async function Sidebar({ staff }: { staff: { id: number; username: string; rank: number } }) { const t = await getTranslations("pages.admin.nav"); const initial = staff.username.charAt(0).toUpperCase(); const navGroups = getNavGroups(t); return ( ); } async function Topbar({ staff }: { staff: { id: number; username: string; rank: number } }) { const t = await getTranslations("pages.admin.nav"); return (

{t("housekeeping")}

{t("hotelManagementPanel")}
{staff.username} {t("rankLabel", { rank: staff.rank })}
); }