Files
fourge-portal/src/context/AuthContext.jsx
T
Krao Hasanee 195c828f8b Improve auth performance: cache profile, remove double fetch, reduce timeout
- 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 <noreply@anthropic.com>
2026-03-27 10:41:42 -04:00

99 lines
2.9 KiB
React
Executable File

import { createContext, useContext, useState, useEffect } from 'react';
import { supabase } from '../lib/supabase';
const AuthContext = createContext(null);
const PROFILE_CACHE_KEY = 'fourge_profile';
export function AuthProvider({ children }) {
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 fetchAndCacheProfile = async (authUser) => {
const { data } = await supabase
.from('profiles')
.select('*, company:companies(id, name, phone, address)')
.eq('id', authUser.id)
.single();
if (data) {
const profile = { ...data, email: authUser.email };
setCurrentUser(profile);
localStorage.setItem(PROFILE_CACHE_KEY, JSON.stringify(profile));
}
};
useEffect(() => {
// 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) {
// 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);
}
});
return () => {
clearTimeout(timeout);
subscription.unsubscribe();
};
}, []);
const login = async (email, password) => {
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) return { error: error.message };
return {};
};
const signup = async (email, password, name) => {
const { error } = await supabase.auth.signUp({
email,
password,
options: { data: { name, role: 'client' } },
});
if (error) return { error: error.message };
const { error: loginError } = await supabase.auth.signInWithPassword({ email, password });
if (loginError) return { error: loginError.message };
return {};
};
const logout = async () => {
await supabase.auth.signOut();
setCurrentUser(null);
localStorage.removeItem(PROFILE_CACHE_KEY);
};
if (loading) return (
<div style={{
minHeight: '100vh', background: '#111111',
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}>
<img src="/fourge-logo.png" alt="Fourge Branding" style={{ width: 160, opacity: 0.6 }} />
</div>
);
return (
<AuthContext.Provider value={{ currentUser, login, signup, logout }}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => useContext(AuthContext);