import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import { supabase } from '@/integrations/supabase/client'; import { Session, User } from '@supabase/supabase-js'; import { useToast } from '@/hooks/use-toast'; type Provider = 'github' | 'google' | 'microsoft'; type AuthContextType = { session: Session | null; user: User | null; profile: any | null; loading: boolean; signIn: (email: string, password: string) => Promise; signUp: (email: string, password: string, fullName: string) => Promise; signOut: () => Promise; signInWithProvider: (provider: Provider) => Promise; }; const AuthContext = createContext(undefined); export const AuthProvider = ({ children }: { children: ReactNode }) => { const [session, setSession] = useState(null); const [user, setUser] = useState(null); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const { toast } = useToast(); useEffect(() => { // Get the initial session supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); setUser(session?.user ?? null); if (session?.user) { fetchProfile(session.user.id); } setLoading(false); }); // Listen for auth changes const { data: { subscription } } = supabase.auth.onAuthStateChange( (_event, session) => { setSession(session); setUser(session?.user ?? null); if (session?.user) { fetchProfile(session.user.id); } else { setProfile(null); } setLoading(false); } ); return () => { subscription.unsubscribe(); }; }, []); const fetchProfile = async (userId: string) => { try { const { data, error } = await supabase .from('profiles') .select('*') .eq('id', userId) .single(); if (error) { console.error('Error fetching profile:', error); return; } setProfile(data); } catch (error) { console.error('Error fetching profile:', error); } }; const signIn = async (email: string, password: string) => { try { setLoading(true); const { error } = await supabase.auth.signInWithPassword({ email, password }); if (error) throw error; toast({ title: "Success!", description: "You are now signed in.", }); } catch (error: any) { toast({ title: "Error signing in", description: error.message, variant: "destructive", }); console.error('Error signing in:', error); throw error; } finally { setLoading(false); } }; const signUp = async (email: string, password: string, fullName: string) => { try { setLoading(true); const { error } = await supabase.auth.signUp({ email, password, options: { data: { full_name: fullName, } } }); if (error) throw error; toast({ title: "Account created!", description: "Please check your email to confirm your account.", }); } catch (error: any) { toast({ title: "Error creating account", description: error.message, variant: "destructive", }); console.error('Error signing up:', error); throw error; } finally { setLoading(false); } }; const signInWithProvider = async (provider: Provider) => { try { setLoading(true); const { error } = await supabase.auth.signInWithOAuth({ provider, options: { redirectTo: window.location.origin + '/dashboard', }, }); if (error) throw error; toast({ title: "Redirecting...", description: `Signing in with ${provider}`, }); } catch (error: any) { toast({ title: `Error signing in with ${provider}`, description: error.message, variant: "destructive", }); console.error(`Error signing in with ${provider}:`, error); setLoading(false); } }; const signOut = async () => { try { setLoading(true); const { error } = await supabase.auth.signOut(); if (error) throw error; toast({ title: "Signed out", description: "You have been successfully signed out.", }); } catch (error: any) { toast({ title: "Error signing out", description: error.message, variant: "destructive", }); console.error('Error signing out:', error); } finally { setLoading(false); } }; return ( {children} ); }; export const useAuth = () => { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };