import Link from "next/link";
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,
Music,
Languages,
Upload,
MessageSquare,
} 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: },
{ href: "/admin/tickets", label: t("tickets"), 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: },
{ href: "/admin/radio/banners", label: t("radioBanners"), icon: },
{ href: "/admin/radio/embed", label: t("radioEmbed"), icon: },
{ href: "/admin/radio/api-keys", label: t("radioApiKeys"), icon: },
{ href: "/admin/radio/moderation", label: t("radioModeration"), icon: },
{ href: "/admin/radio/settings", label: t("radioSettings"), icon: },
{ href: "/admin/radio/monitoring", label: t("radioMonitoring"), icon: },
{ href: "/admin/radio/points", label: t("radioPoints"), icon: },
{ href: "/admin/radio/ranks", label: t("radioRanks"), icon: },
{ href: "/admin/radio/autodj", label: t("radioAutodj"), 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/sounds", label: t("sounds"), icon: },
{ href: "/admin/translations", label: t("translations"), icon: },
{ href: "/admin/import", label: t("import"), icon: },
{ href: "/admin/settings", label: t("settings"), icon: },
],
},
];
}
export default async function AdminLayout({ children }: { children: ReactNode }) {
const staff = await requireStaff();
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 (
);
}
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 })}
);
}