refactor(sidebar): use next/link for client-side navigation
This commit is contained in:
parent
01f4820f2e
commit
6cce6116b8
4 changed files with 30 additions and 10 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import Link from "next/link"
|
||||||
import { ChevronRight, type LucideIcon } from "lucide-react"
|
import { ChevronRight, type LucideIcon } from "lucide-react"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -44,10 +45,10 @@ export function NavCore({
|
||||||
<Collapsible key={item.title} asChild defaultOpen={item.isActive}>
|
<Collapsible key={item.title} asChild defaultOpen={item.isActive}>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton asChild tooltip={item.title}>
|
<SidebarMenuButton asChild tooltip={item.title}>
|
||||||
<a href={item.url}>
|
<Link href={item.url}>
|
||||||
<item.icon />
|
<item.icon />
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
</a>
|
</Link>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
{item.items?.length ? (
|
{item.items?.length ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -62,10 +63,10 @@ export function NavCore({
|
||||||
{item.items?.map((subItem) => (
|
{item.items?.map((subItem) => (
|
||||||
<SidebarMenuSubItem key={subItem.title}>
|
<SidebarMenuSubItem key={subItem.title}>
|
||||||
<SidebarMenuSubButton asChild>
|
<SidebarMenuSubButton asChild>
|
||||||
<a href={subItem.url}>
|
<Link href={subItem.url}>
|
||||||
{subItem.icon ? <subItem.icon /> : null}
|
{subItem.icon ? <subItem.icon /> : null}
|
||||||
<span>{subItem.title}</span>
|
<span>{subItem.title}</span>
|
||||||
</a>
|
</Link>
|
||||||
</SidebarMenuSubButton>
|
</SidebarMenuSubButton>
|
||||||
</SidebarMenuSubItem>
|
</SidebarMenuSubItem>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import Link from "next/link"
|
||||||
import {
|
import {
|
||||||
Folder,
|
Folder,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
|
|
@ -43,10 +44,10 @@ export function NavProjects({
|
||||||
{projects.map((item) => (
|
{projects.map((item) => (
|
||||||
<SidebarMenuItem key={item.name}>
|
<SidebarMenuItem key={item.name}>
|
||||||
<SidebarMenuButton asChild>
|
<SidebarMenuButton asChild>
|
||||||
<a href={item.url}>
|
<Link href={item.url}>
|
||||||
<item.icon />
|
<item.icon />
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</a>
|
</Link>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import Link from "next/link"
|
||||||
import { type LucideIcon } from "lucide-react"
|
import { type LucideIcon } from "lucide-react"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -26,10 +27,10 @@ export function NavSecondary({
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<SidebarMenuItem key={item.title}>
|
<SidebarMenuItem key={item.title}>
|
||||||
<SidebarMenuButton asChild size="sm">
|
<SidebarMenuButton asChild size="sm">
|
||||||
<a href={item.url}>
|
<Link href={item.url}>
|
||||||
<item.icon />
|
<item.icon />
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
</a>
|
</Link>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, FileTextIcon, LogOut, Sparkles } from "lucide-react";
|
import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, FileTextIcon, LogOut, Sparkles } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
import {
|
import {
|
||||||
|
|
@ -30,6 +32,21 @@ export function NavUser({
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
const { isMobile } = useSidebar();
|
const { isMobile } = useSidebar();
|
||||||
|
const router = useRouter();
|
||||||
|
const [loggingOut, setLoggingOut] = useState(false);
|
||||||
|
|
||||||
|
const handleLogout = async () => {
|
||||||
|
setLoggingOut(true);
|
||||||
|
try {
|
||||||
|
await fetch("/api/users/logout", { method: "POST" });
|
||||||
|
} catch {
|
||||||
|
// ignore network errors; redirect anyway
|
||||||
|
} finally {
|
||||||
|
setLoggingOut(false);
|
||||||
|
}
|
||||||
|
router.push("/");
|
||||||
|
router.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
|
|
@ -92,9 +109,9 @@ export function NavUser({
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem onSelect={() => handleLogout()}>
|
||||||
<LogOut />
|
<LogOut />
|
||||||
Log out
|
{loggingOut ? "Logging out..." : "Log out"}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue