ai-chatbot/app/(admin)/settings/_components/admin-settings-navigation.tsx

149 lines
4.3 KiB
TypeScript

"use client";
import Link from "next/link";
import { ArrowLeft } from "lucide-react";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { ADMIN_SETTINGS_NAV_ITEMS } from "../_lib/settings-navigation";
import type { AdminSettingsNavItem } from "../_lib/types";
function SettingsQuickAction({
activeTab,
item,
onTabChange,
stretched = false,
}: {
activeTab: string;
item: AdminSettingsNavItem;
onTabChange: (value: string) => void;
stretched?: boolean;
}) {
const Icon = item.icon;
const className =
item.value === activeTab
? "border-foreground/10 bg-foreground text-background shadow-sm hover:!bg-foreground/90 hover:!text-background dark:border-white/20 dark:bg-white dark:text-black dark:hover:!bg-white/90 dark:hover:!text-black"
: "border-transparent bg-transparent text-muted-foreground hover:!border-border/80 hover:!bg-zinc-100 hover:!text-foreground dark:hover:!bg-zinc-900/50";
const layoutClassName = stretched
? "h-8 w-full min-w-0 justify-center gap-1.5 rounded-md border px-2.5 text-xs"
: "h-8 shrink-0 gap-1.5 rounded-md border px-2.5 text-xs";
if (item.href) {
return (
<Button
asChild
className={`${layoutClassName} ${className}`}
size="sm"
variant="ghost"
>
<Link href={item.href}>
<Icon className="h-3.5 w-3.5" />
<span className={stretched ? "truncate" : ""}>{item.label}</span>
</Link>
</Button>
);
}
return (
<Button
className={`${layoutClassName} ${className}`}
onClick={() => onTabChange(item.value)}
size="sm"
variant="ghost"
>
<Icon className="h-3.5 w-3.5" />
<span className={stretched ? "truncate" : ""}>{item.label}</span>
</Button>
);
}
export function AdminSettingsNavigation({
activeTab,
onTabChange,
}: {
activeTab: string;
onTabChange: (value: string) => void;
}) {
const router = useRouter();
const activeItem = ADMIN_SETTINGS_NAV_ITEMS.find(
(item) => item.value === activeTab
);
const handleSelectChange = (value: string) => {
const nextItem = ADMIN_SETTINGS_NAV_ITEMS.find(
(item) => item.value === value
);
if (nextItem?.href) {
router.push(nextItem.href);
return;
}
onTabChange(value);
};
return (
<nav
aria-label="系统设置导航"
className="sticky top-2 z-30 rounded-lg border bg-background/95 p-2 shadow-sm backdrop-blur supports-[backdrop-filter]:bg-background/85"
>
<div className="md:hidden">
<div className="flex items-center gap-2">
<Select onValueChange={handleSelectChange} value={activeTab}>
<SelectTrigger className="h-8 flex-1 border-border/70 bg-background shadow-none">
<SelectValue placeholder={activeItem?.label || "选择设置项"} />
</SelectTrigger>
<SelectContent>
{ADMIN_SETTINGS_NAV_ITEMS.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Button
asChild
className="h-8 rounded-md border-border/70 px-2.5 text-xs"
size="sm"
variant="outline"
>
<Link href="/">
<ArrowLeft className="h-3.5 w-3.5" />
返回
</Link>
</Button>
</div>
</div>
<div className="hidden min-w-0 grid-cols-7 gap-1 md:grid xl:grid-cols-[repeat(13,minmax(78px,1fr))_auto]">
{ADMIN_SETTINGS_NAV_ITEMS.map((item) => (
<SettingsQuickAction
activeTab={activeTab}
item={item}
key={item.value}
onTabChange={onTabChange}
stretched
/>
))}
<Button
asChild
className="h-8 min-w-0 rounded-md border-border/70 px-2.5 text-xs"
size="sm"
variant="outline"
>
<Link href="/">
<ArrowLeft className="h-3.5 w-3.5" />
返回工作台
</Link>
</Button>
</div>
</nav>
);
}