lovart3/components/app-sidebar.tsx
Your Name 28d0f445c5 feat: move navigation to right sidebar
Switch top navigation to a vertical right rail with icon+label and adjust page layouts to reserve sidebar space.
2026-02-03 15:15:06 +08:00

137 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import type { User } from "next-auth";
import { useState } from "react";
import { toast } from "sonner";
import { useSWRConfig } from "swr";
import { unstable_serialize } from "swr/infinite";
import { PlusIcon, TrashIcon } from "@/components/icons";
import {
getChatHistoryPaginationKey,
SidebarHistory,
} from "@/components/sidebar-history";
import { SidebarUserNav } from "@/components/sidebar-user-nav";
import { Button } from "@/components/ui/button";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarMenu,
useSidebar,
} from "@/components/ui/sidebar";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "./ui/alert-dialog";
import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
export function AppSidebar({ user }: { user: User | undefined }) {
const router = useRouter();
const { setOpenMobile } = useSidebar();
const { mutate } = useSWRConfig();
const [showDeleteAllDialog, setShowDeleteAllDialog] = useState(false);
const handleDeleteAll = () => {
const deletePromise = fetch("/api/history", {
method: "DELETE",
});
toast.promise(deletePromise, {
loading: "正在删除所有会话...",
success: () => {
mutate(unstable_serialize(getChatHistoryPaginationKey));
router.push("/");
setShowDeleteAllDialog(false);
return "所有会话已删除";
},
error: "删除会话失败,请稍后重试",
});
};
return (
<>
<Sidebar className="group-data-[side=left]:border-r-0">
<SidebarHeader>
<SidebarMenu>
<div className="flex flex-row items-center justify-between w-full">
{/* Logo removed */}
<div className="flex-1" />
<div className="flex flex-row gap-1">
{user && (
<Tooltip>
<TooltipTrigger asChild>
<Button
className="h-8 p-1 md:h-fit md:p-2"
onClick={() => setShowDeleteAllDialog(true)}
type="button"
variant="ghost"
>
<TrashIcon />
</Button>
</TooltipTrigger>
<TooltipContent align="end" side="bottom" className="hidden md:block">
删除所有会话
</TooltipContent>
</Tooltip>
)}
<Tooltip>
<TooltipTrigger asChild>
<Button
className="h-8 p-1 md:h-fit md:p-2"
onClick={() => {
setOpenMobile(false);
router.push("/");
router.refresh();
}}
type="button"
variant="ghost"
>
<PlusIcon />
</Button>
</TooltipTrigger>
<TooltipContent align="end" side="bottom" className="hidden md:block">
新建会话
</TooltipContent>
</Tooltip>
</div>
</div>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<SidebarHistory user={user} />
</SidebarContent>
<SidebarFooter>{user && <SidebarUserNav user={user} />}</SidebarFooter>
</Sidebar>
<AlertDialog
onOpenChange={setShowDeleteAllDialog}
open={showDeleteAllDialog}
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>确定删除全部会话?</AlertDialogTitle>
<AlertDialogDescription>
操作不可撤销,所有会话记录将从服务器永久移除。
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>取消</AlertDialogCancel>
<AlertDialogAction onClick={handleDeleteAll}>
删除所有
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
}