From b339dd865cfe5f3856c8d13a957673946ef69ec9 Mon Sep 17 00:00:00 2001 From: pradeepkumar Date: Fri, 13 Mar 2026 12:41:35 +0530 Subject: [PATCH] feat: Implement guest menu in the common header for unauthenticated users and enhance JWT session handling for user profile updates. --- public/assets/icons/signin-user-icon.svg | 3 + src/auth.ts | 8 +- src/components/layout/CommonHeader.tsx | 94 +++++++++++++++++-- .../profile/SpecializationSection.tsx | 4 +- 4 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 public/assets/icons/signin-user-icon.svg diff --git a/public/assets/icons/signin-user-icon.svg b/public/assets/icons/signin-user-icon.svg new file mode 100644 index 0000000..879dae7 --- /dev/null +++ b/public/assets/icons/signin-user-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/auth.ts b/src/auth.ts index df0c178..3c2fffb 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -145,7 +145,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ return true; }, - async jwt({ token, user }) { + async jwt({ token, user, trigger, session: updateData }) { if (user) { token.id = user.id; token.name = user.name; @@ -158,6 +158,12 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ token.accessTokenIssuedAt = Date.now(); } + // Handle session updates from client-side updateSession() calls + if (trigger === "update" && updateData?.user) { + if (updateData.user.name) token.name = updateData.user.name; + if (updateData.user.image !== undefined) token.picture = updateData.user.image; + } + // Auto-refresh the access token if it's about to expire (refresh 2 minutes before expiry) // Backend JWT_ACCESS_EXPIRATION=15m, so refresh at ~13 minutes const ACCESS_TOKEN_MAX_AGE = 13 * 60 * 1000; // 13 minutes in ms diff --git a/src/components/layout/CommonHeader.tsx b/src/components/layout/CommonHeader.tsx index 6db4381..4dc4758 100644 --- a/src/components/layout/CommonHeader.tsx +++ b/src/components/layout/CommonHeader.tsx @@ -19,8 +19,10 @@ const navLinks = [ export function CommonHeader() { const { data: session } = useSession(); const [showProfileMenu, setShowProfileMenu] = useState(false); + const [showGuestMenu, setShowGuestMenu] = useState(false); const [showMobileMenu, setShowMobileMenu] = useState(false); const profileMenuRef = useRef(null); + const guestMenuRef = useRef(null); const mobileMenuRef = useRef(null); const [profileImage, setProfileImage] = useState(null); const [profileName, setProfileName] = useState(null); @@ -32,19 +34,22 @@ export function CommonHeader() { if (profileMenuRef.current && !profileMenuRef.current.contains(event.target as Node)) { setShowProfileMenu(false); } + if (guestMenuRef.current && !guestMenuRef.current.contains(event.target as Node)) { + setShowGuestMenu(false); + } if (mobileMenuRef.current && !mobileMenuRef.current.contains(event.target as Node)) { setShowMobileMenu(false); } } - if (showProfileMenu || showMobileMenu) { + if (showProfileMenu || showGuestMenu || showMobileMenu) { document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; - }, [showProfileMenu, showMobileMenu]); + }, [showProfileMenu, showGuestMenu, showMobileMenu]); // Fetch profile data (image and name) from backend based on user role const fetchProfileData = useCallback(async () => { @@ -292,14 +297,83 @@ export function CommonHeader() { ) : ( - - Login - +
+ + + {showGuestMenu && ( +
+
+ +
+ User +

+ Sign in or create account to continue +

+
+ + setShowGuestMenu(false)} + > + Settings +
+

Account Settings

+

Profile, Security

+
+ + + setShowGuestMenu(false)} + > + Notifications +

Notification Settings

+ + +
+ setShowGuestMenu(false)} + className="flex-1 h-[37px] bg-[#e58625] rounded-[15px] flex items-center justify-center font-fractul text-[14px] text-white hover:bg-[#d47920] transition-colors" + > + Sign up + + setShowGuestMenu(false)} + className="flex-1 h-[37px] border border-[#e58625] rounded-[15px] flex items-center justify-center font-fractul text-[14px] text-[#e58625] hover:bg-[#e58625]/5 transition-colors" + > + Login + +
+
+ )} +
)} {/* Mobile Menu Button */} diff --git a/src/components/profile/SpecializationSection.tsx b/src/components/profile/SpecializationSection.tsx index 6197636..5317d5a 100644 --- a/src/components/profile/SpecializationSection.tsx +++ b/src/components/profile/SpecializationSection.tsx @@ -29,7 +29,7 @@ export function SpecializationSection({ fieldsData }: SpecializationSectionProps {/* Top row - up to 3 cards */} {topRowFields.length > 0 && ( -
0 && ( -