From a7c1fd49be44d11d12adb9dfbbde600298d1fc5c Mon Sep 17 00:00:00 2001 From: Utkarsh-Patel-13 Date: Sat, 2 Aug 2025 21:36:04 -0700 Subject: [PATCH] sticky top navigation & user data in user nav --- .../[search_space_id]/client-layout.tsx | 4 +- .../components/sidebar/app-sidebar.tsx | 3 +- surfsense_web/components/sidebar/nav-user.tsx | 74 +++++++++++++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx index 97c7894..d785bdf 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx @@ -26,8 +26,8 @@ export function DashboardClientLayout({ navMain={navMain} /> -
-
+
+
diff --git a/surfsense_web/components/sidebar/app-sidebar.tsx b/surfsense_web/components/sidebar/app-sidebar.tsx index 5071de4..70eb3fb 100644 --- a/surfsense_web/components/sidebar/app-sidebar.tsx +++ b/surfsense_web/components/sidebar/app-sidebar.tsx @@ -181,7 +181,6 @@ export const AppSidebar = memo(function AppSidebar({ navMain = defaultData.navMain, navSecondary = defaultData.navSecondary, RecentChats = defaultData.RecentChats, - user = defaultData.user, ...props }: AppSidebarProps) { // Process navMain to resolve icon names to components @@ -243,7 +242,7 @@ export const AppSidebar = memo(function AppSidebar({ {/* User Profile Section */} - + ); diff --git a/surfsense_web/components/sidebar/nav-user.tsx b/surfsense_web/components/sidebar/nav-user.tsx index 664052d..114f42a 100644 --- a/surfsense_web/components/sidebar/nav-user.tsx +++ b/surfsense_web/components/sidebar/nav-user.tsx @@ -1,8 +1,8 @@ "use client"; -import { BadgeCheck, ChevronsUpDown, LogOut, Settings, User } from "lucide-react"; +import { BadgeCheck, ChevronsUpDown, LogOut, Settings, User as UserIcon } from "lucide-react"; import { useParams, useRouter } from "next/navigation"; -import { memo, useCallback } from "react"; +import { memo, useCallback, useEffect, useState } from "react"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { DropdownMenu, @@ -20,6 +20,15 @@ import { SidebarMenuItem, useSidebar, } from "@/components/ui/sidebar"; +import { apiClient } from "@/lib/api"; + +interface User { + id: string; + email: string; + is_active: boolean; + is_superuser: boolean; + is_verified: boolean; +} interface UserData { name: string; @@ -28,11 +37,50 @@ interface UserData { } // Memoized NavUser component for better performance -export const NavUser = memo(function NavUser({ user }: { user: UserData }) { +export const NavUser = memo(function NavUser() { const { isMobile } = useSidebar(); const router = useRouter(); const { search_space_id } = useParams(); + // User state management + const [user, setUser] = useState(null); + const [isLoadingUser, setIsLoadingUser] = useState(true); + const [userError, setUserError] = useState(null); + + // Fetch user details + useEffect(() => { + const fetchUser = async () => { + try { + if (typeof window === "undefined") return; + + try { + const userData = await apiClient.get("users/me"); + setUser(userData); + setUserError(null); + } catch (error) { + console.error("Error fetching user:", error); + setUserError(error instanceof Error ? error.message : "Unknown error occurred"); + } finally { + setIsLoadingUser(false); + } + } catch (error) { + console.error("Error in fetchUser:", error); + setIsLoadingUser(false); + } + }; + + fetchUser(); + }, []); + + // Create user object for display + const userData: UserData = { + name: user?.email ? user.email.split("@")[0] : "User", + email: + user?.email || + (isLoadingUser ? "Loading..." : userError ? "Error loading user" : "Unknown User"), + avatar: "/icon-128.png", // Default avatar + }; + // Memoized logout handler const handleLogout = useCallback(() => { if (typeof window !== "undefined") { @@ -42,9 +90,9 @@ export const NavUser = memo(function NavUser({ user }: { user: UserData }) { }, [router]); // Get user initials for avatar fallback - const userInitials = user.name + const userInitials = userData.name .split(" ") - .map((n) => n[0]) + .map((n: string) => n[0]) .join("") .toUpperCase() .slice(0, 2); @@ -61,14 +109,14 @@ export const NavUser = memo(function NavUser({ user }: { user: UserData }) { aria-label="User menu" > - + - {userInitials || } + {userInitials || }
- {user.name} - {user.email} + {userData.name} + {userData.email}
@@ -82,14 +130,14 @@ export const NavUser = memo(function NavUser({ user }: { user: UserData }) {
- + - {userInitials || } + {userInitials || }
- {user.name} - {user.email} + {userData.name} + {userData.email}