Refactor: Simplify auth and profile handling

This commit is contained in:
gpt-engineer-app[bot]
2025-10-13 17:22:56 +00:00
parent be26c08640
commit 149c0704fe
9 changed files with 78 additions and 122 deletions

View File

@@ -8,12 +8,10 @@ import { authLog, authWarn, authError } from '@/lib/authLogger';
interface AuthContextType {
user: User | null;
session: Session | null;
profile: Profile | null;
loading: boolean;
pendingEmail: string | null;
sessionError: string | null;
signOut: () => Promise<void>;
refreshProfile: () => Promise<void>;
verifySession: () => Promise<boolean>;
clearPendingEmail: () => void;
}
@@ -23,61 +21,16 @@ const AuthContext = createContext<AuthContextType | undefined>(undefined);
function AuthProviderComponent({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [session, setSession] = useState<Session | null>(null);
const [profile, setProfile] = useState<Profile | null>(null);
const [loading, setLoading] = useState(true);
const [pendingEmail, setPendingEmail] = useState<string | null>(null);
const [sessionError, setSessionError] = useState<string | null>(null);
// Refs for lifecycle and cleanup management
const isMountedRef = useRef(true);
const profileFetchTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const novuUpdateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const fetchedUserIdRef = useRef<string | null>(null);
const previousEmailRef = useRef<string | null>(null);
const fetchProfile = async (userId: string) => {
console.log('[Auth] 📡 fetchProfile called for userId:', userId);
try {
const { data, error } = await supabase
.from('profiles')
.select(`*, location:locations(*)`)
.eq('user_id', userId)
.maybeSingle();
console.log('[Auth] 📦 Profile fetch result:', {
hasData: !!data,
hasError: !!error,
avatar_url: data?.avatar_url
});
if (error && error.code !== 'PGRST116') {
authError('[Auth] ❌ Error fetching profile:', error);
return;
}
if (isMountedRef.current && data) {
console.log('[Auth] ✅ Setting profile state with data:', {
userId: data.user_id,
username: data.username,
avatar_url: data.avatar_url,
});
setProfile(data as Profile);
} else {
console.log('[Auth] ⚠️ NOT setting profile - mounted:', isMountedRef.current, 'hasData:', !!data);
}
} catch (error) {
authError('[Auth] ❌ Exception in fetchProfile:', error);
}
};
const refreshProfile = async () => {
if (user) {
await fetchProfile(user.id);
}
};
// Verify session is still valid - simplified
const verifySession = async (updateLoadingState = false) => {
const verifySession = async () => {
try {
const { data: { session }, error } = await supabase.auth.getSession();
@@ -95,7 +48,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
authLog('[Auth] Session verified:', session.user.email);
// Update state if session was found but not set
if (!user && isMountedRef.current) {
if (!user) {
setSession(session);
setUser(session.user);
}
@@ -142,17 +95,13 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
authLog('[Auth] INITIAL_SESSION - no user');
setSession(null);
setUser(null);
setProfile(null);
setLoading(false);
return;
}
} else if (event === 'SIGNED_OUT') {
authLog('[Auth] SIGNED_OUT - clearing state');
console.log('[Auth] 🔴 SIGNED_OUT - clearing profile and fetch tracking');
fetchedUserIdRef.current = null;
setSession(null);
setUser(null);
setProfile(null);
setLoading(false);
return;
} else {
@@ -222,24 +171,6 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
if (currentEmail) {
previousEmailRef.current = currentEmail;
}
// Handle profile fetching for authenticated users (async, doesn't block loading)
if (session?.user) {
// Only fetch if we haven't fetched for this user yet
if (fetchedUserIdRef.current !== session.user.id) {
console.log('[Auth] 🔄 Fetching profile for user:', session.user.id);
fetchedUserIdRef.current = session.user.id;
if (profileFetchTimeoutRef.current) {
clearTimeout(profileFetchTimeoutRef.current);
profileFetchTimeoutRef.current = null;
}
fetchProfile(session.user.id);
} else {
console.log('[Auth] ✅ Profile already fetched for user:', session.user.id);
}
}
});
// THEN get initial session (this may trigger INITIAL_SESSION event)
@@ -258,15 +189,9 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
return () => {
authLog('[Auth] Cleaning up auth provider');
isMountedRef.current = false;
fetchedUserIdRef.current = null;
subscription.unsubscribe();
// Clear any pending timeouts
if (profileFetchTimeoutRef.current) {
clearTimeout(profileFetchTimeoutRef.current);
profileFetchTimeoutRef.current = null;
}
if (novuUpdateTimeoutRef.current) {
clearTimeout(novuUpdateTimeoutRef.current);
novuUpdateTimeoutRef.current = null;
@@ -289,12 +214,10 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
const value = {
user,
session,
profile,
loading,
pendingEmail,
sessionError,
signOut,
refreshProfile,
verifySession,
clearPendingEmail,
};