Fix sidebar bug

main
Deardo Satria 2 days ago
parent 54dfbd2691
commit 1ab0c2e321

@ -1,5 +1,6 @@
"use client"; "use client";
import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { ChevronRightIcon } from "lucide-react"; import { ChevronRightIcon } from "lucide-react";
@ -21,7 +22,9 @@ import {
SidebarMenuSubButton, SidebarMenuSubButton,
SidebarMenuSubItem, SidebarMenuSubItem,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { navItems } from "./nav-items"; import { navItems, type NavItem } from "./nav-items";
type NavGroupItem = Extract<NavItem, { items: unknown }>;
export function AppSidebar({ footer }: { footer: React.ReactNode }) { export function AppSidebar({ footer }: { footer: React.ReactNode }) {
const pathname = usePathname(); const pathname = usePathname();
@ -36,11 +39,49 @@ export function AppSidebar({ footer }: { footer: React.ReactNode }) {
<SidebarMenu className="gap-0.5"> <SidebarMenu className="gap-0.5">
{navItems.map((item) => {navItems.map((item) =>
"items" in item ? ( "items" in item ? (
<Collapsible <NavGroup key={item.title} item={item} pathname={pathname} />
key={item.title} ) : (
defaultOpen={item.items.some((sub) => <SidebarMenuItem key={item.href}>
pathname.startsWith(sub.href), <SidebarMenuButton
render={<Link href={item.href} />}
isActive={pathname === item.href}
>
<item.icon />
<span>{item.title}</span>
</SidebarMenuButton>
</SidebarMenuItem>
),
)} )}
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>{footer}</SidebarFooter>
</Sidebar>
);
}
// Controlled karena sidebar tetap ter-mount antar navigasi; defaultOpen yang berubah memicu warning Base UI.
function NavGroup({
item,
pathname,
}: {
item: NavGroupItem;
pathname: string;
}) {
const isActive = item.items.some((sub) => pathname.startsWith(sub.href));
const [open, setOpen] = useState(isActive);
const [prevActive, setPrevActive] = useState(isActive);
// Buka otomatis saat navigasi masuk ke grup ini, tanpa menutup grup yang dibuka manual.
if (isActive !== prevActive) {
setPrevActive(isActive);
if (isActive) setOpen(true);
}
return (
<Collapsible
open={open}
onOpenChange={setOpen}
render={<SidebarMenuItem />} render={<SidebarMenuItem />}
> >
<CollapsibleTrigger render={<SidebarMenuButton />}> <CollapsibleTrigger render={<SidebarMenuButton />}>
@ -63,22 +104,5 @@ export function AppSidebar({ footer }: { footer: React.ReactNode }) {
</SidebarMenuSub> </SidebarMenuSub>
</CollapsibleContent> </CollapsibleContent>
</Collapsible> </Collapsible>
) : (
<SidebarMenuItem key={item.href}>
<SidebarMenuButton
render={<Link href={item.href} />}
isActive={pathname === item.href}
>
<item.icon />
<span>{item.title}</span>
</SidebarMenuButton>
</SidebarMenuItem>
),
)}
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>{footer}</SidebarFooter>
</Sidebar>
); );
} }

@ -0,0 +1,34 @@
"use client";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { useRouter } from "next/navigation";
export default function NotFoundPage() {
const router = useRouter();
return (
<div className="grid min-h-svh place-items-center bg-background px-6 text-foreground">
<div className="w-full max-w-sm text-center">
<p className="font-mono text-xs tracking-[0.3em] text-muted-foreground uppercase">
Cleo Minimarket
</p>
<h1 className="mt-4 text-7xl font-semibold tracking-tighter tabular-nums">
404
</h1>
<p className="mt-3 text-lg font-medium">Halaman tidak ditemukan</p>
<p className="mt-2 text-sm text-muted-foreground">
Alamat yang dibuka tidak ada atau sudah dipindah.
</p>
<div className="mt-8 border-t border-dashed pt-6">
<Button
className="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring"
onClick={() => {
router.back();
}}
>
Kembali
</Button>
</div>
</div>
</div>
);
}
Loading…
Cancel
Save