109 lines
3.1 KiB
TypeScript
109 lines
3.1 KiB
TypeScript
'use client';
|
|
|
|
import { createContext, useContext, useEffect, useState, useCallback } from 'react';
|
|
import { User, Session, AuthError } from '@supabase/supabase-js';
|
|
import { supabase } from '@/lib/supabase';
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
session: Session | null;
|
|
loading: boolean;
|
|
signUp: (email: string, password: string, metadata?: Record<string, unknown>) => Promise<{ error: AuthError | null }>;
|
|
signIn: (email: string, password: string) => Promise<{ error: AuthError | null }>;
|
|
signInWithOAuth: (provider: 'google' | 'github' | 'azure') => Promise<void>;
|
|
signOut: () => Promise<void>;
|
|
resetPassword: (email: string) => Promise<{ error: AuthError | null }>;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [session, setSession] = useState<Session | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
// Initiale Session holen
|
|
supabase.auth.getSession().then(({ data: { session } }) => {
|
|
setSession(session);
|
|
setUser(session?.user ?? null);
|
|
setLoading(false);
|
|
});
|
|
|
|
// Auth State Listener
|
|
const { data: { subscription } } = supabase.auth.onAuthStateChange(
|
|
(_event, session) => {
|
|
setSession(session);
|
|
setUser(session?.user ?? null);
|
|
}
|
|
);
|
|
|
|
return () => subscription.unsubscribe();
|
|
}, []);
|
|
|
|
const signUp = useCallback(
|
|
async (email: string, password: string, metadata?: Record<string, unknown>) => {
|
|
const { error } = await supabase.auth.signUp({
|
|
email,
|
|
password,
|
|
options: { data: metadata },
|
|
});
|
|
return { error };
|
|
},
|
|
[]
|
|
);
|
|
|
|
const signIn = useCallback(async (email: string, password: string) => {
|
|
const { error } = await supabase.auth.signInWithPassword({
|
|
email,
|
|
password,
|
|
});
|
|
return { error };
|
|
}, []);
|
|
|
|
const signInWithOAuth = useCallback(async (provider: 'google' | 'github' | 'azure') => {
|
|
await supabase.auth.signInWithOAuth({
|
|
provider,
|
|
options: {
|
|
redirectTo: `${window.location.origin}/auth/callback`,
|
|
},
|
|
});
|
|
}, []);
|
|
|
|
const signOut = useCallback(async () => {
|
|
await supabase.auth.signOut();
|
|
}, []);
|
|
|
|
const resetPassword = useCallback(async (email: string) => {
|
|
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
|
redirectTo: `${window.location.origin}/auth/reset-password`,
|
|
});
|
|
return { error };
|
|
}, []);
|
|
|
|
return (
|
|
<AuthContext.Provider
|
|
value={{
|
|
user,
|
|
session,
|
|
loading,
|
|
signUp,
|
|
signIn,
|
|
signInWithOAuth,
|
|
signOut,
|
|
resetPassword,
|
|
}}
|
|
>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext);
|
|
if (context === undefined) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
}
|