import { Link } from "wouter" import { SearchIcon, SettingsIcon, TagsIcon, ArchiveIcon, UserIcon, LayoutListIcon, PanelLeftIcon, PanelLeftCloseIcon, MenuIcon, XIcon, type LucideIcon } from "lucide-react" import { Button, buttonVariants } from "@/components/ui/button.tsx" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip.tsx" import { useLogin } from "@/state/user.ts"; import { useNavItems } from "./navAtom"; import { Separator } from "../ui/separator"; import { cn } from "@/lib/utils"; import { useMemo } from "react"; import { useAtom, useAtomValue } from "jotai"; import { sidebarAtom } from "./sidebarAtom"; const NAV_ICON_CLASS = "size-4"; const NAV_LINKS = { search: { to: "/search", Icon: SearchIcon }, tags: { to: "/tags", Icon: TagsIcon }, difference: { to: "/difference", Icon: ArchiveIcon }, queue: { to: "/queue", Icon: LayoutListIcon }, settings: { to: "/setting", Icon: SettingsIcon } } satisfies Record; type NavLinkKey = keyof typeof NAV_LINKS; type NavItemData = { key: string; icon: React.ReactNode; to?: string; name: string; className?: string; } const createNavItem = (key: NavLinkKey, name: string, className?: string): NavItemData => { const { Icon, to } = NAV_LINKS[key]; return { key, icon: , to, name, className }; }; function useNavItemsData() { const loginInfo = useLogin(); const isLoggedIn = Boolean(loginInfo); return useMemo(() => { const accountItem: NavItemData = { key: "account", icon: , to: isLoggedIn ? "/profile" : "/login", name: isLoggedIn ? "Profiles" : "Login", }; return ({ main: [ createNavItem("search", "Search"), createNavItem("tags", "Tags"), createNavItem("difference", "Difference"), ], footer: [ accountItem, createNavItem("settings", "Settings") ], bottomNav: (useCustomItems: boolean) => useCustomItems ? [] : [ createNavItem("tags", "Tags"), createNavItem("difference", "Diff"), { ...accountItem, name: isLoggedIn ? "Profile" : "Login" }, createNavItem("settings", "Settings") ] }) }, [isLoggedIn]); } export function NavList() { const customNavItems = useNavItems(); const { main, footer } = useNavItemsData(); return ( ); } // 사이드바 토글 버튼 export function SidebarToggle() { const [sidebarState, setSidebarState] = useAtom(sidebarAtom); const isOpen = sidebarState.isCollapsed; const onToggle = () => setSidebarState((s) => ({ ...s, isCollapsed: !s.isCollapsed })); return ( {isOpen ? "Close sidebar" : "Open sidebar"} ); } // 모바일용 사이드바 토글 버튼 export function MobileSidebarToggle() { const [sidebarState, setSidebarState] = useAtom(sidebarAtom); const isOpen = sidebarState.isCollapsed; const onToggle = () => setSidebarState((s) => ({ ...s, isCollapsed: !s.isCollapsed })); return ( ); } // 사이드바 네비게이션 아이템 interface SidebarNavItemProps { children: React.ReactNode; name: string; to?: string; className?: string; onClick?: () => void; } export function SidebarNavItem({ children, name, to, className, onClick }: SidebarNavItemProps) { const sidebarState = useAtomValue(sidebarAtom); const isCollapsed = sidebarState.isCollapsed; const buttonClass = cn( buttonVariants({ variant: "ghost", size: "sm" }), "rounded-none md:rounded-md", isCollapsed ? "justify-center size-10 p-0" : "justify-start gap-3 h-10 px-3", className ); const Container = to ? ({ children, ref }: { children: React.ReactNode, ref?: React.Ref }) => ( {children} ) : ({ children, ref }: { children: React.ReactNode, ref?: React.Ref }) => ( ); const linkContent = ( {children} {name} ); if (isCollapsed) { return ( {linkContent} {name} ); } return linkContent; } // 데스크탑용 사이드바 네비게이션 export function SidebarNav() { const customNavItems = useNavItems(); const { main, footer } = useNavItemsData(); return (
{footer.map(({ key, icon, to, name, className }) => ( {icon} ))}
); } // 모바일용 하단 네비게이션 export function BottomNav() { const customNavItems = useNavItems(); const { main, bottomNav } = useNavItemsData(); const searchItem = { ...main[0] }; // Search item const items = bottomNav(Boolean(customNavItems)); return ( ); }