"use client"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { useMemo, type ReactElement } from "react"; import { useTranslation } from "react-i18next"; import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarRail, SidebarSeparator, } from "@/components/ui/sidebar"; import { adminNavLabel } from "@/lib/admin-nav-label"; import { cn } from "@/lib/utils"; import { resolveAdminNavIcon } from "@/modules/_config/admin-nav-icons"; import { ADMIN_BASE } from "@/modules/_config/admin-nav"; import { useAdminProfile, useAdminSessionStore } from "@/stores/admin-session"; /** 与常见导航项文字宽度接近,避免整齐灰条 */ const SIDEBAR_NAV_SKELETON_WIDTHS = ["68%", "82%", "58%", "74%", "64%", "78%", "55%", "70%", "62%"] as const; function SidebarNavSkeletonRow({ labelWidth, delayMs, }: { labelWidth: string; delayMs: number; }): ReactElement { return (
); } function AdminSidebarSkeleton(): ReactElement { const { t } = useTranslation("common"); return (
N lotto
{t("sidebar.workspace", { defaultValue: "Workspace" })} {SIDEBAR_NAV_SKELETON_WIDTHS.map((width, i) => ( ))} {t("auth.checking")} ); } function isActive(pathname: string, item: { href: string; activeMatchPrefix?: string; segment?: string }): boolean { const { href, activeMatchPrefix, segment } = item; const prefix = activeMatchPrefix ?? href; if (prefix === ADMIN_BASE || prefix === `${ADMIN_BASE}/`) { return pathname === ADMIN_BASE || pathname === `${ADMIN_BASE}/`; } // Keep "settings" independent from its child routes like /admin/settings/currencies. if (segment === "settings") { return pathname === href; } return pathname === prefix || pathname.startsWith(`${prefix}/`); } export function AdminAppSidebar() { const { t } = useTranslation(["common", "dashboard", "players", "draws", "config", "wallet", "risk", "settlement", "jackpot", "reconcile", "tickets", "audit", "reports"]); const pathname = usePathname(); const shellAuthPending = useAdminSessionStore((s) => s.shellAuthPending); const profile = useAdminProfile(); if (shellAuthPending) { return ; } const visibleNav = useMemo( () => (profile?.navigation ?? []).filter((item) => item.segment !== "risk"), [profile?.navigation], ); return ( } className="h-full min-h-0 justify-start px-1 py-0 hover:bg-transparent group-data-[collapsible=icon]:justify-center" >
N lotto
{t("sidebar.workspace", { ns: "common", defaultValue: "Workspace" })} {visibleNav.map((item) => { const Icon = resolveAdminNavIcon(item.segment); return ( } className="font-medium text-sidebar-foreground/90 hover:text-sidebar-accent-foreground data-active:bg-red-600 data-active:text-white data-active:shadow-sm" > {adminNavLabel(item.segment, t, item.label)} ); })} ); }