1- import { useState , useEffect , useRef } from 'react' ;
2- import { useAuthContext } from '@/contexts/AuthContext' ;
1+ import { useState } from 'react' ;
2+ import { useAuth } from '@/contexts/AuthContext' ;
33import {
44 DropdownMenu ,
55 DropdownMenuContent ,
@@ -11,193 +11,28 @@ import {
1111} from '@/components/ui/dropdown-menu' ;
1212import { Button } from '@/components/ui/button' ;
1313import { Avatar , AvatarFallback , AvatarImage } from '@/components/ui/avatar' ;
14- import { LogOut , Settings , User , Bug , RefreshCw } from 'lucide-react' ;
14+ import { LogOut , Settings , User } from 'lucide-react' ;
1515import AuthDialog from './auth/AuthDialog' ;
1616import { useToast } from '@/hooks/use-toast' ;
1717
18- // Fallback function to directly check localStorage if context fails
19- function getAuthUserFromStorage ( ) {
20- try {
21- const storedUser = localStorage . getItem ( 'auth_user' ) ;
22- if ( storedUser ) {
23- return JSON . parse ( storedUser ) ;
24- }
25- return null ;
26- } catch ( e ) {
27- console . error ( '[UserProfileButton] Error parsing stored user:' , e ) ;
28- return null ;
29- }
30- }
31-
3218export default function UserProfileButton ( ) {
33- // Capture raw AuthContext first to debug it
34- const contextValue = useAuthContext ( ) ;
35- console . log ( '[UserProfileButton] Raw AuthContext:' , contextValue ) ;
36-
37- // Extract expected properties
38- const { user : contextUser , signOut, loading } = contextValue ;
39-
40- // Setup alternative user source from localStorage as fallback
41- const [ fallbackUser , setFallbackUser ] = useState ( getAuthUserFromStorage ( ) ) ;
42- const [ forceAuthenticated , setForceAuthenticated ] = useState ( false ) ;
43- const [ showDebugInfo , setShowDebugInfo ] = useState ( false ) ;
44- const [ debugCounts , setDebugCounts ] = useState ( { contextCheck : 0 , storageCheck : 0 } ) ;
45- const authIssueDetected = useRef ( false ) ;
46- const checkInterval = useRef < number | null > ( null ) ;
47-
48- // If we need to, we'll use fallback
49- const user = contextUser || fallbackUser ;
50-
19+ const { currentUser, logout, isLoading } = useAuth ( ) ;
5120 const [ authDialogOpen , setAuthDialogOpen ] = useState ( false ) ;
5221 const [ authMode , setAuthMode ] = useState < 'login' | 'signup' > ( 'login' ) ;
5322 const { toast } = useToast ( ) ;
5423
55- // Function to force check auth state - can be called manually
56- const forceAuthCheck = ( ) => {
57- console . log ( '[UserProfileButton] Manual auth check triggered' ) ;
58-
59- // Always re-read from localStorage
60- const storedUser = getAuthUserFromStorage ( ) ;
61- setDebugCounts ( prev => ( { ...prev , storageCheck : prev . storageCheck + 1 } ) ) ;
62-
63- // Update our knowledge of the context
64- setDebugCounts ( prev => ( { ...prev , contextCheck : prev . contextCheck + 1 } ) ) ;
65-
66- if ( storedUser && ! contextUser ) {
67- console . log ( '[UserProfileButton] Manual check found user in localStorage but not in context' ) ;
68- setFallbackUser ( storedUser ) ;
69- setForceAuthenticated ( true ) ;
70- authIssueDetected . current = true ;
71-
72- toast ( {
73- title : 'Auth Fallback Activated' ,
74- description : 'Using localStorage authentication data since context is missing.' ,
75- } ) ;
76-
77- return true ;
78- } else if ( contextUser ) {
79- console . log ( '[UserProfileButton] Manual check found user in context:' , contextUser . email ) ;
80- return true ;
81- } else if ( ! storedUser && ! contextUser ) {
82- console . log ( '[UserProfileButton] Manual check found no user in storage or context' ) ;
83- setFallbackUser ( null ) ;
84- setForceAuthenticated ( false ) ;
85- return false ;
86- }
87-
88- return ! ! contextUser || ! ! storedUser ;
89- } ;
90-
91- // Check localStorage on mount and periodically
92- useEffect ( ( ) => {
93- console . log ( '[UserProfileButton] Component mounted' ) ;
94-
95- // Immediate check on mount
96- const storedUser = getAuthUserFromStorage ( ) ;
97- if ( storedUser && ! contextUser && ! authIssueDetected . current ) {
98- console . log ( '[UserProfileButton] Found user in localStorage but not in context, using fallback' ) ;
99- setFallbackUser ( storedUser ) ;
100- setForceAuthenticated ( true ) ;
101- authIssueDetected . current = true ;
102-
103- toast ( {
104- title : 'Authentication Status' ,
105- description : 'User session detected in storage but not in context. Using backup authentication.' ,
106- } ) ;
107- }
108-
109- // Setup periodic localStorage check in case auth state changes
110- if ( checkInterval . current === null ) {
111- checkInterval . current = window . setInterval ( ( ) => {
112- const latestStoredUser = getAuthUserFromStorage ( ) ;
113-
114- // Log full context value every few seconds to debug
115- console . log ( '[UserProfileButton] Periodic check context:' , {
116- contextUser : contextUser ? {
117- email : contextUser . email ,
118- id : contextUser . id
119- } : null ,
120- contextIsAuthenticated : contextValue . isAuthenticated ,
121- storedUserExists : ! ! latestStoredUser ,
122- currentForceState : forceAuthenticated
123- } ) ;
124-
125- if ( latestStoredUser && ! contextUser && ! authIssueDetected . current ) {
126- console . log ( '[UserProfileButton] Auth state inconsistency detected, activating fallback' ) ;
127- setFallbackUser ( latestStoredUser ) ;
128- setForceAuthenticated ( true ) ;
129- authIssueDetected . current = true ;
130- } else if ( ! latestStoredUser && forceAuthenticated ) {
131- console . log ( '[UserProfileButton] User no longer in localStorage, deactivating fallback' ) ;
132- setFallbackUser ( null ) ;
133- setForceAuthenticated ( false ) ;
134- }
135- } , 2000 ) ;
136-
137- console . log ( '[UserProfileButton] Set up periodic auth check interval:' , checkInterval . current ) ;
138- }
139-
140- return ( ) => {
141- console . log ( '[UserProfileButton] Component unmounting, clearing interval' ) ;
142- if ( checkInterval . current !== null ) {
143- clearInterval ( checkInterval . current ) ;
144- checkInterval . current = null ;
145- }
146- } ;
147- } , [ contextUser , forceAuthenticated ] ) ;
148-
149- // Clear force authenticated if we get a context user
150- useEffect ( ( ) => {
151- if ( contextUser && forceAuthenticated ) {
152- console . log ( '[UserProfileButton] Context user found, clearing forced auth state' ) ;
153- setForceAuthenticated ( false ) ;
154- }
155- } , [ contextUser ] ) ;
156-
15724 const handleLogout = async ( ) => {
158- console . log ( '[UserProfileButton] Logout started' ) ;
15925 try {
160- // Always clear localStorage first
161- localStorage . removeItem ( 'auth_user' ) ;
162- setFallbackUser ( null ) ;
163- setForceAuthenticated ( false ) ;
164- authIssueDetected . current = false ;
165-
166- // Then try context logout
167- if ( typeof signOut === 'function' ) {
168- console . log ( '[UserProfileButton] Calling context signOut function' ) ;
169- await signOut ( ) ;
170- } else {
171- console . log ( '[UserProfileButton] No signOut function in context' ) ;
172- }
173-
174- console . log ( '[UserProfileButton] Logout completed' ) ;
26+ await logout ( ) ;
17527 toast ( {
17628 title : 'Logged out successfully' ,
17729 description : 'You have been logged out of your account' ,
17830 } ) ;
179-
180- // Extra check to ensure we're really logged out
181- setTimeout ( ( ) => {
182- if ( getAuthUserFromStorage ( ) ) {
183- console . warn ( '[UserProfileButton] User still in localStorage after logout!' ) ;
184- localStorage . removeItem ( 'auth_user' ) ;
185- }
186- } , 500 ) ;
18731 } catch ( error ) {
188- console . error ( '[UserProfileButton] Logout error:' , error ) ;
189- toast ( {
190- title : 'Error' ,
191- description : 'Failed to log out. Please try again.' ,
192- variant : 'destructive' ,
193- } ) ;
32+ // Error already handled in auth context
19433 }
19534 } ;
19635
197- const toggleDebugInfo = ( ) => {
198- setShowDebugInfo ( ! showDebugInfo ) ;
199- } ;
200-
20136 const getInitials = ( name : string ) => {
20237 if ( ! name ) return 'U' ;
20338 return name
@@ -209,14 +44,112 @@ export default function UserProfileButton() {
20944 } ;
21045
21146 const getDisplayName = ( ) => {
212- if ( user ?. displayName ) {
213- return user . displayName ;
47+ if ( currentUser ?. displayName ) {
48+ return currentUser . displayName ;
21449 }
215- if ( user ?. email ) {
216- return user . email . split ( '@' ) [ 0 ] ;
50+ if ( currentUser ?. email ) {
51+ return currentUser . email . split ( '@' ) [ 0 ] ;
21752 }
21853 return 'User' ;
21954 } ;
22055
22156 const renderAuthenticatedView = ( ) => {
222- console . log ( '[UserProfil
57+ const initials = getInitials ( getDisplayName ( ) ) ;
58+ const profileImage = currentUser ?. photoURL || '' ;
59+
60+ return (
61+ < DropdownMenu >
62+ < DropdownMenuTrigger asChild >
63+ < Button variant = "ghost" className = "relative h-10 w-10 rounded-full" >
64+ < Avatar className = "h-10 w-10" >
65+ < AvatarImage src = { profileImage } alt = { getDisplayName ( ) } />
66+ < AvatarFallback > { initials } </ AvatarFallback >
67+ </ Avatar >
68+ </ Button >
69+ </ DropdownMenuTrigger >
70+ < DropdownMenuContent className = "w-56" align = "end" forceMount >
71+ < DropdownMenuLabel className = "font-normal" >
72+ < div className = "flex flex-col space-y-1" >
73+ < p className = "text-sm font-medium leading-none" > { getDisplayName ( ) } </ p >
74+ < p className = "text-xs leading-none text-muted-foreground" >
75+ { currentUser ?. email }
76+ </ p >
77+ </ div >
78+ </ DropdownMenuLabel >
79+ < DropdownMenuSeparator />
80+ < DropdownMenuGroup >
81+ < DropdownMenuItem >
82+ < User className = "mr-2 h-4 w-4" />
83+ < span > Profile</ span >
84+ </ DropdownMenuItem >
85+ < DropdownMenuItem >
86+ < Settings className = "mr-2 h-4 w-4" />
87+ < span > Settings</ span >
88+ </ DropdownMenuItem >
89+ </ DropdownMenuGroup >
90+ < DropdownMenuSeparator />
91+ < DropdownMenuItem onClick = { handleLogout } >
92+ < LogOut className = "mr-2 h-4 w-4" />
93+ < span > Log out</ span >
94+ </ DropdownMenuItem >
95+ </ DropdownMenuContent >
96+ </ DropdownMenu >
97+ ) ;
98+ } ;
99+
100+ const renderUnauthenticatedView = ( ) => {
101+ return (
102+ < >
103+ < div className = "hidden md:flex space-x-2" >
104+ < Button
105+ variant = "outline"
106+ onClick = { ( ) => {
107+ setAuthMode ( 'login' ) ;
108+ setAuthDialogOpen ( true ) ;
109+ } }
110+ >
111+ Log in
112+ </ Button >
113+ < Button
114+ onClick = { ( ) => {
115+ setAuthMode ( 'signup' ) ;
116+ setAuthDialogOpen ( true ) ;
117+ } }
118+ >
119+ Sign up
120+ </ Button >
121+ </ div >
122+ < div className = "md:hidden" >
123+ < Button
124+ variant = "ghost"
125+ className = "h-10 w-10 rounded-full"
126+ onClick = { ( ) => {
127+ setAuthMode ( 'login' ) ;
128+ setAuthDialogOpen ( true ) ;
129+ } }
130+ >
131+ < Avatar className = "h-10 w-10" >
132+ < AvatarFallback >
133+ < User className = "h-5 w-5" />
134+ </ AvatarFallback >
135+ </ Avatar >
136+ </ Button >
137+ </ div >
138+
139+ < AuthDialog
140+ isOpen = { authDialogOpen }
141+ onOpenChange = { setAuthDialogOpen }
142+ defaultMode = { authMode }
143+ />
144+ </ >
145+ ) ;
146+ } ;
147+
148+ if ( isLoading ) {
149+ return (
150+ < div className = "h-10 w-10 rounded-full bg-slate-200 dark:bg-slate-700 animate-pulse" />
151+ ) ;
152+ }
153+
154+ return currentUser ? renderAuthenticatedView ( ) : renderUnauthenticatedView ( ) ;
155+ }
0 commit comments