feat(layout): login, uygulama kabuğu, alt menü, hızlı ekle ve dashboard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Logo } from "@/components/brand/logo";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuBadge,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarRail,
|
||||
useSidebar,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { ADMIN_NAV, MAIN_NAV, isActivePath, isAvailable, type NavItem } from "./nav-config";
|
||||
|
||||
function NavList({ items, pathname }: { items: NavItem[]; pathname: string }) {
|
||||
const { setOpenMobile } = useSidebar();
|
||||
return (
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
if (!isAvailable(item)) {
|
||||
return (
|
||||
<SidebarMenuItem key={item.href}>
|
||||
<SidebarMenuButton
|
||||
aria-disabled
|
||||
disabled
|
||||
tooltip={`${item.label} · ${tr.common.comingSoon}`}
|
||||
>
|
||||
<Icon />
|
||||
<span>{item.label}</span>
|
||||
</SidebarMenuButton>
|
||||
<SidebarMenuBadge className="text-[0.65rem] opacity-70">
|
||||
{tr.common.comingSoon}
|
||||
</SidebarMenuBadge>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
}
|
||||
const active = isActivePath(pathname, item.href);
|
||||
return (
|
||||
<SidebarMenuItem key={item.href}>
|
||||
<SidebarMenuButton asChild isActive={active} tooltip={item.label}>
|
||||
<Link
|
||||
href={item.href}
|
||||
aria-current={active ? "page" : undefined}
|
||||
onClick={() => setOpenMobile(false)}
|
||||
>
|
||||
<Icon />
|
||||
<span>{item.label}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
);
|
||||
}
|
||||
|
||||
/** Masaüstünde sabit yan menü; mobilde "Daha fazla" ile açılan Sheet. */
|
||||
export function AppSidebar({ isAdmin, version }: { isAdmin: boolean; version: string }) {
|
||||
const pathname = usePathname();
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader className="h-14 justify-center px-3">
|
||||
<Link
|
||||
href="/dashboard"
|
||||
aria-label={tr.nav.dashboard}
|
||||
className="group-data-[collapsible=icon]:hidden"
|
||||
>
|
||||
<Logo />
|
||||
</Link>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>{tr.nav.main}</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<NavList items={MAIN_NAV} pathname={pathname} />
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
{isAdmin ? (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>{tr.nav.admin}</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<NavList items={ADMIN_NAV} pathname={pathname} />
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
) : null}
|
||||
</SidebarContent>
|
||||
<SidebarFooter className="px-4 pb-3 text-xs text-muted-foreground group-data-[collapsible=icon]:hidden">
|
||||
{tr.app.name} · {tr.app.version} {version}
|
||||
</SidebarFooter>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user