Skip to content

Commit c0b2a5e

Browse files
committed
Document WIP integration plan and finalize UserProfileButton
1 parent f5f992b commit c0b2a5e

2 files changed

Lines changed: 236 additions & 176 deletions

File tree

Lines changed: 109 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { useState, useEffect, useRef } from 'react';
2-
import { useAuthContext } from '@/contexts/AuthContext';
1+
import { useState } from 'react';
2+
import { useAuth } from '@/contexts/AuthContext';
33
import {
44
DropdownMenu,
55
DropdownMenuContent,
@@ -11,193 +11,28 @@ import {
1111
} from '@/components/ui/dropdown-menu';
1212
import { Button } from '@/components/ui/button';
1313
import { 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';
1515
import AuthDialog from './auth/AuthDialog';
1616
import { 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-
3218
export 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

Comments
 (0)