description-improv / src /contexts /AuthContext.tsx
Felix Zieger
update
018dc4e
import { createContext, useState, useEffect, useContext, ReactNode } from "react";
import { supabase } from "@/integrations/supabase/client";
import { Session, User } from "@supabase/supabase-js";
type AuthContextType = {
session: Session | null;
user: User | null;
loading: boolean;
signIn: (email: string, password: string) => Promise<{
error: Error | null;
success: boolean;
}>;
signUp: (email: string, password: string) => Promise<{
error: Error | null;
success: boolean;
}>;
signInWithGoogle: () => Promise<{
error: Error | null;
success: boolean;
}>;
signInWithGitHub: () => Promise<{
error: Error | null;
success: boolean;
}>;
signOut: () => Promise<void>;
};
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [session, setSession] = useState<Session | null>(null);
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Set up auth state listener FIRST
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(event, session) => {
setSession(session);
setUser(session?.user ?? null);
}
);
// THEN check for existing session
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
setUser(session?.user ?? null);
setLoading(false);
});
return () => subscription.unsubscribe();
}, []);
const signIn = async (email: string, password: string) => {
try {
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
return { error, success: !error };
} catch (error) {
return { error: error as Error, success: false };
}
};
const signUp = async (email: string, password: string) => {
try {
const { error } = await supabase.auth.signUp({
email,
password,
});
return { error, success: !error };
} catch (error) {
return { error: error as Error, success: false };
}
};
const signInWithGoogle = async () => {
try {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
queryParams: {
access_type: 'offline',
prompt: 'consent',
},
},
});
return { error, success: !error };
} catch (error) {
return { error: error as Error, success: false };
}
};
const signInWithGitHub = async () => {
try {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
});
return { error, success: !error };
} catch (error) {
return { error: error as Error, success: false };
}
};
const signOut = async () => {
await supabase.auth.signOut();
};
return (
<AuthContext.Provider
value={{
session,
user,
loading,
signIn,
signUp,
signInWithGoogle,
signInWithGitHub,
signOut,
}}
>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};