From 195c828f8b62a0dc6f2e4abefe7580407d41cf8c Mon Sep 17 00:00:00 2001 From: Krao Hasanee Date: Fri, 27 Mar 2026 10:41:42 -0400 Subject: [PATCH] Improve auth performance: cache profile, remove double fetch, reduce timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Seed currentUser from localStorage instantly on load (no loading flash) - Remove getSession() duplicate — onAuthStateChange handles everything - Fetch fresh profile in background while cached version shows immediately - Reduce fallback timeout from 5s to 2s - Explicit Supabase client auth options for reliability Co-Authored-By: Claude Sonnet 4.6 --- src/context/AuthContext.jsx | 43 ++++++++++++++++++++++++------------- src/lib/supabase.js | 8 ++++++- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/context/AuthContext.jsx b/src/context/AuthContext.jsx index d0a260a..6b1fde3 100755 --- a/src/context/AuthContext.jsx +++ b/src/context/AuthContext.jsx @@ -3,36 +3,49 @@ import { supabase } from '../lib/supabase'; const AuthContext = createContext(null); +const PROFILE_CACHE_KEY = 'fourge_profile'; + export function AuthProvider({ children }) { - const [currentUser, setCurrentUser] = useState(null); + const [currentUser, setCurrentUser] = useState(() => { + // Seed from cache instantly — no loading flash for returning users + try { + const cached = localStorage.getItem(PROFILE_CACHE_KEY); + return cached ? JSON.parse(cached) : null; + } catch { return null; } + }); const [loading, setLoading] = useState(true); - const fetchProfile = async (authUser) => { + const fetchAndCacheProfile = async (authUser) => { const { data } = await supabase .from('profiles') .select('*, company:companies(id, name, phone, address)') .eq('id', authUser.id) .single(); - if (data) setCurrentUser({ ...data, email: authUser.email }); + if (data) { + const profile = { ...data, email: authUser.email }; + setCurrentUser(profile); + localStorage.setItem(PROFILE_CACHE_KEY, JSON.stringify(profile)); + } }; useEffect(() => { - const timeout = setTimeout(() => setLoading(false), 5000); - - supabase.auth.getSession().then(async ({ data: { session } }) => { - if (session?.user) await fetchProfile(session.user); - clearTimeout(timeout); - setLoading(false); - }).catch(() => { - clearTimeout(timeout); - setLoading(false); - }); + // Fallback — stop blocking after 2s max + const timeout = setTimeout(() => setLoading(false), 2000); + let resolved = false; const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => { if (session?.user) { - await fetchProfile(session.user); + // Fetch fresh profile in background (cache already seeded above) + fetchAndCacheProfile(session.user); } else { setCurrentUser(null); + localStorage.removeItem(PROFILE_CACHE_KEY); + } + + if (!resolved) { + resolved = true; + clearTimeout(timeout); + setLoading(false); } }); @@ -55,7 +68,6 @@ export function AuthProvider({ children }) { options: { data: { name, role: 'client' } }, }); if (error) return { error: error.message }; - // Auto sign-in immediately after signup (no email confirmation required) const { error: loginError } = await supabase.auth.signInWithPassword({ email, password }); if (loginError) return { error: loginError.message }; return {}; @@ -64,6 +76,7 @@ export function AuthProvider({ children }) { const logout = async () => { await supabase.auth.signOut(); setCurrentUser(null); + localStorage.removeItem(PROFILE_CACHE_KEY); }; if (loading) return ( diff --git a/src/lib/supabase.js b/src/lib/supabase.js index 36f5b6d..f7a91a1 100755 --- a/src/lib/supabase.js +++ b/src/lib/supabase.js @@ -5,4 +5,10 @@ const key = import.meta.env.VITE_SUPABASE_ANON_KEY; if (!url || !key) throw new Error('Missing Supabase environment variables. Check VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.'); -export const supabase = createClient(url, key); +export const supabase = createClient(url, key, { + auth: { + persistSession: true, + autoRefreshToken: true, + detectSessionInUrl: false, + }, +});