header.tsx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import Link from "next/link";
  2. import Image from "next/image";
  3. import { getKindeServerSession, LoginLink, LogoutLink, RegisterLink } from "@kinde-oss/kinde-auth-nextjs/server";
  4. import {
  5. NavigationMenu,
  6. NavigationMenuContent,
  7. NavigationMenuItem,
  8. NavigationMenuLink,
  9. NavigationMenuList,
  10. NavigationMenuTrigger,
  11. } from "@/components/ui/navigation-menu";
  12. import { Button } from "@/components/ui/button";
  13. import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
  14. import { Menu, FileText, Home, Folder, Settings, User, LogOut, LogIn } from "lucide-react";
  15. import { cn } from "@/lib/utils";
  16. import React from "react";
  17. const navigationItems = [
  18. {
  19. title: "Files",
  20. href: "/files",
  21. description: "Browse and manage your files",
  22. icon: Folder,
  23. },
  24. {
  25. title: "API Docs",
  26. href: "/api-docs",
  27. description: "View API documentation",
  28. icon: FileText,
  29. },
  30. ];
  31. const userMenuItems = [
  32. {
  33. title: "Profile",
  34. href: "/profile",
  35. description: "Manage your profile settings",
  36. icon: User,
  37. },
  38. {
  39. title: "Settings",
  40. href: "/settings",
  41. description: "Configure your preferences",
  42. icon: Settings,
  43. },
  44. ];
  45. export default async function Header() {
  46. const { isAuthenticated, getUser } = getKindeServerSession();
  47. const isLoggedIn = await isAuthenticated();
  48. const user = isLoggedIn ? await getUser() : null;
  49. return (
  50. <header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
  51. <div className="container flex h-16 items-center justify-between">
  52. <div className="flex items-center gap-6">
  53. <Link href="/" className="flex items-center space-x-2" >
  54. <Image
  55. src="/vtorio.svg"
  56. alt="vtor.io"
  57. width={32}
  58. height={8}
  59. className="h-8 w-auto"
  60. priority
  61. />
  62. </Link>
  63. <NavigationMenu className="hidden md:flex">
  64. <NavigationMenuList>
  65. {navigationItems.map((item) => (
  66. <NavigationMenuItem key={item.title}>
  67. <NavigationMenuLink
  68. href={item.href}
  69. className={cn(
  70. "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50"
  71. )}>
  72. <item.icon className="mr-2 h-4 w-4" />
  73. {item.title}
  74. </NavigationMenuLink>
  75. </NavigationMenuItem>
  76. ))}
  77. </NavigationMenuList>
  78. </NavigationMenu>
  79. </div>
  80. <div className="flex items-center gap-4">
  81. {isLoggedIn ? (
  82. <>
  83. <NavigationMenu className="hidden md:flex">
  84. <NavigationMenuList>
  85. <NavigationMenuItem>
  86. <NavigationMenuTrigger className="h-9">
  87. <div className="flex items-center gap-2">
  88. <Image
  89. className="rounded-full"
  90. src={user?.picture || "/default-avatar.png"}
  91. alt="User Avatar"
  92. width={24}
  93. height={24}
  94. />
  95. <span className="text-sm font-medium">{user?.given_name || user?.email}</span>
  96. </div>
  97. </NavigationMenuTrigger>
  98. <NavigationMenuContent>
  99. <ul className="grid gap-3 p-6 w-[300px]">
  100. {userMenuItems.map((item) => (
  101. <li key={item.title}>
  102. <NavigationMenuLink asChild>
  103. <Link
  104. href={item.href}
  105. className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground">
  106. <div className="flex items-center gap-2">
  107. <item.icon className="h-4 w-4" />
  108. <div className="text-sm font-medium leading-none">{item.title}</div>
  109. </div>
  110. <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
  111. {item.description}
  112. </p>
  113. </Link>
  114. </NavigationMenuLink>
  115. </li>
  116. ))}
  117. <li>
  118. <LogoutLink className="block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground">
  119. <div className="flex items-center gap-2">
  120. <LogOut className="h-4 w-4" />
  121. <div className="text-sm font-medium leading-none">Logout</div>
  122. </div>
  123. <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
  124. Sign out of your account
  125. </p>
  126. </LogoutLink>
  127. </li>
  128. </ul>
  129. </NavigationMenuContent>
  130. </NavigationMenuItem>
  131. </NavigationMenuList>
  132. </NavigationMenu>
  133. </>
  134. ) : (
  135. <div className="hidden md:flex items-center gap-2">
  136. <LoginLink>
  137. <Button variant="ghost" size="sm">
  138. <LogIn className="h-4 w-4 mr-2" />
  139. Login
  140. </Button>
  141. </LoginLink>
  142. <RegisterLink>
  143. <Button size="sm">Sign Up</Button>
  144. </RegisterLink>
  145. </div>
  146. )}
  147. {/* Mobile Menu */}
  148. <Sheet>
  149. <SheetTrigger asChild className="md:hidden">
  150. <Button variant="ghost" size="icon">
  151. <Menu className="h-5 w-5" />
  152. <span className="sr-only">Toggle menu</span>
  153. </Button>
  154. </SheetTrigger>
  155. <SheetContent side="right" className="w-[300px]">
  156. <div className="flex flex-col space-y-4 mt-8">
  157. <Link href="/" className="flex items-center space-x-2" >
  158. <Home className="h-4 w-4" />
  159. <span>Home</span>
  160. </Link>
  161. {navigationItems.map((item) => (
  162. <Link
  163. key={item.title}
  164. href={item.href}
  165. className="flex items-center space-x-2" >
  166. <item.icon className="h-4 w-4" />
  167. <span>{item.title}</span>
  168. </Link>
  169. ))}
  170. {isLoggedIn ? (
  171. <>
  172. <div className="border-t pt-4">
  173. <div className="flex items-center space-x-2 mb-4">
  174. <Image
  175. className="rounded-full"
  176. src={user?.picture || "/default-avatar.png"}
  177. alt="User Avatar"
  178. width={32}
  179. height={32}
  180. />
  181. <span className="font-medium">{user?.given_name || user?.email}</span>
  182. </div>
  183. {userMenuItems.map((item) => (
  184. <Link
  185. key={item.title}
  186. href={item.href}
  187. className="flex items-center space-x-2 py-2" >
  188. <item.icon className="h-4 w-4" />
  189. <span>{item.title}</span>
  190. </Link>
  191. ))}
  192. <LogoutLink className="flex items-center space-x-2 py-2 text-red-600">
  193. <LogOut className="h-4 w-4" />
  194. <span>Logout</span>
  195. </LogoutLink>
  196. </div>
  197. </>
  198. ) : (
  199. <div className="border-t pt-4 space-y-2">
  200. <LoginLink>
  201. <Button variant="ghost" className="w-full justify-start">
  202. <LogIn className="h-4 w-4 mr-2" />
  203. Login
  204. </Button>
  205. </LoginLink>
  206. <RegisterLink>
  207. <Button className="w-full">Sign Up</Button>
  208. </RegisterLink>
  209. </div>
  210. )}
  211. </div>
  212. </SheetContent>
  213. </Sheet>
  214. </div>
  215. </div>
  216. </header>
  217. );
  218. }