feat(dashboard): integrate SessionProvider and update NavUser for session data

- Integrated `SessionProvider` from `next-auth/react` to manage user sessions.
- Updated `AppSidebar` to use `SessionProvider` and reflect user data.
- Modified `NavUser` to display user info based on session, with default fallback.
This commit is contained in:
ngc2207 2024-12-09 00:37:35 +08:00
parent 474c71bf96
commit 5f427a5032
3 changed files with 124 additions and 83 deletions

View File

@ -11,6 +11,7 @@ import {
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"; } from "@/components/ui/breadcrumb";
import { SessionProvider } from "next-auth/react";
import { AppSidebar } from "@/components/app-sidebar"; import { AppSidebar } from "@/components/app-sidebar";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
@ -18,30 +19,32 @@ export default function DashboardLayout({
children, children,
}: Readonly<{ children: React.ReactNode }>) { }: Readonly<{ children: React.ReactNode }>) {
return ( return (
<SidebarProvider> <SessionProvider>
<AppSidebar /> <SidebarProvider>
<SidebarInset> <AppSidebar />
<header className="flex h-16 shrink-0 items-center gap-2"> <SidebarInset>
<div className="flex items-center gap-2 px-4"> <header className="flex h-16 shrink-0 items-center gap-2">
<SidebarTrigger className="-ml-1" /> <div className="flex items-center gap-2 px-4">
<Separator orientation="vertical" className="mr-2 h-4" /> <SidebarTrigger className="-ml-1" />
<Breadcrumb> <Separator orientation="vertical" className="mr-2 h-4" />
<BreadcrumbList> <Breadcrumb>
<BreadcrumbItem className="hidden md:block"> <BreadcrumbList>
<BreadcrumbLink href="#"> <BreadcrumbItem className="hidden md:block">
Building Your Application <BreadcrumbLink href="#">
</BreadcrumbLink> Building Your Application
</BreadcrumbItem> </BreadcrumbLink>
<BreadcrumbSeparator className="hidden md:block" /> </BreadcrumbItem>
<BreadcrumbItem> <BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbPage>Data Fetching</BreadcrumbPage> <BreadcrumbItem>
</BreadcrumbItem> <BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbList> </BreadcrumbItem>
</Breadcrumb> </BreadcrumbList>
</div> </Breadcrumb>
</header> </div>
{children} </header>
</SidebarInset> {children}
</SidebarProvider> </SidebarInset>
</SidebarProvider>
</SessionProvider>
); );
} }

View File

@ -29,9 +29,9 @@ import { NavSecondary } from "@/components/nav-secondary";
const data = { const data = {
user: { user: {
name: "shadcn", name: "gitea",
email: "m@example.com", email: "about@gitea.com",
avatar: "/avatars/shadcn.jpg", avatar: "/gitea.svg",
}, },
navMain: [ navMain: [
{ {

View File

@ -1,31 +1,41 @@
"use client"; "use client";
import { import {
BadgeCheck,
Bell, Bell,
ChevronsUpDown, LogIn,
CreditCard,
LogOut, LogOut,
Sparkles, Sparkles,
BadgeCheck,
CreditCard,
ChevronsUpDown,
} from "lucide-react"; } from "lucide-react";
import { useMemo } from "react";
import { import {
useSidebar,
SidebarMenu, SidebarMenu,
SidebarMenuButton, SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuGroup,
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuContent,
DropdownMenuTrigger, DropdownMenuTrigger,
DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { useSession } from "next-auth/react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
export function NavUser({ const UserAvatar = ({ src, alt }: { src: string; alt: string }) => (
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={src} alt={alt} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
);
export const NavUser = ({
user, user,
}: { }: {
user: { user: {
@ -33,8 +43,20 @@ export function NavUser({
email: string; email: string;
avatar: string; avatar: string;
}; };
}) { }) => {
const { isMobile } = useSidebar(); const { isMobile } = useSidebar();
const { data: session } = useSession();
const currentUser = useMemo(() => {
if (session?.user) {
return {
name: session.user.name ?? "Unknown",
email: session.user.email ?? "Unknown",
avatar: session.user.image ?? "/gitea.svg",
};
}
return user;
}, [session, user]);
return ( return (
<SidebarMenu> <SidebarMenu>
@ -45,13 +67,12 @@ export function NavUser({
size="lg" size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
> >
<Avatar className="h-8 w-8 rounded-lg"> <UserAvatar src={currentUser.avatar} alt={currentUser.name} />
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight"> <div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">{user.name}</span> <span className="truncate font-semibold">
<span className="truncate text-xs">{user.email}</span> {currentUser.name}
</span>
<span className="truncate text-xs">{currentUser.email}</span>
</div> </div>
<ChevronsUpDown className="ml-auto size-4" /> <ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton> </SidebarMenuButton>
@ -62,48 +83,65 @@ export function NavUser({
align="end" align="end"
sideOffset={4} sideOffset={4}
> >
<DropdownMenuLabel className="p-0 font-normal"> {session?.user ? (
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm"> <>
<Avatar className="h-8 w-8 rounded-lg"> <DropdownMenuLabel className="p-0 font-normal">
<AvatarImage src={user.avatar} alt={user.name} /> <div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<AvatarFallback className="rounded-lg">CN</AvatarFallback> <UserAvatar
</Avatar> src={currentUser.avatar}
<div className="grid flex-1 text-left text-sm leading-tight"> alt={currentUser.name}
<span className="truncate font-semibold">{user.name}</span> />
<span className="truncate text-xs">{user.email}</span> <div className="grid flex-1 text-left text-sm leading-tight">
</div> <span className="truncate font-semibold">
</div> {currentUser.name}
</DropdownMenuLabel> </span>
<DropdownMenuSeparator /> <span className="truncate text-xs">
<DropdownMenuGroup> {currentUser.email}
<DropdownMenuItem> </span>
<Sparkles /> </div>
Upgrade to Pro </div>
</DropdownMenuItem> </DropdownMenuLabel>
</DropdownMenuGroup> <DropdownMenuSeparator />
<DropdownMenuSeparator /> <DropdownMenuGroup>
<DropdownMenuGroup> <DropdownMenuItem>
<DropdownMenuItem> <Sparkles />
<BadgeCheck /> Upgrade to Pro
Account </DropdownMenuItem>
</DropdownMenuItem> </DropdownMenuGroup>
<DropdownMenuItem> <DropdownMenuSeparator />
<CreditCard /> <DropdownMenuGroup>
Billing <DropdownMenuItem>
</DropdownMenuItem> <BadgeCheck />
<DropdownMenuItem> Account
<Bell /> </DropdownMenuItem>
Notifications <DropdownMenuItem>
</DropdownMenuItem> <CreditCard />
</DropdownMenuGroup> Billing
<DropdownMenuSeparator /> </DropdownMenuItem>
<DropdownMenuItem> <DropdownMenuItem>
<LogOut /> <Bell />
Log out Notifications
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<LogOut />
Log out
</DropdownMenuItem>
</DropdownMenuGroup>
</>
) : (
<DropdownMenuGroup>
<DropdownMenuItem>
<LogIn />
Log in
</DropdownMenuItem>
</DropdownMenuGroup>
)}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</SidebarMenuItem> </SidebarMenuItem>
</SidebarMenu> </SidebarMenu>
); );
} };