122 lines
3.1 KiB
TypeScript
122 lines
3.1 KiB
TypeScript
import type { Session, User } from '@supabase/supabase-js';
|
|
import { useRouter, useSegments } from 'expo-router';
|
|
import React, {
|
|
createContext,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
} from 'react';
|
|
import { supabase } from '@/services/supabase';
|
|
|
|
type AuthContextValue = {
|
|
initialized: boolean;
|
|
session: Session | null;
|
|
user: User | null;
|
|
signIn: (email: string, password: string) => Promise<{ error?: string }>;
|
|
signUp: (params: {
|
|
email: string;
|
|
password: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
}) => Promise<{ error?: string }>;
|
|
signOut: () => Promise<void>;
|
|
};
|
|
|
|
const AuthContext = createContext<AuthContextValue | null>(null);
|
|
|
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
const [initialized, setInitialized] = useState(false);
|
|
const [session, setSession] = useState<Session | null>(null);
|
|
const segments = useSegments();
|
|
const router = useRouter();
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
void supabase.auth.getSession().then(({ data }) => {
|
|
if (!cancelled) {
|
|
setSession(data.session ?? null);
|
|
setInitialized(true);
|
|
}
|
|
});
|
|
const {
|
|
data: { subscription },
|
|
} = supabase.auth.onAuthStateChange((_event, nextSession) => {
|
|
setSession(nextSession);
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
subscription.unsubscribe();
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (!initialized) return;
|
|
const root = segments[0];
|
|
if (!session?.user && root === '(tabs)') {
|
|
router.replace('/auth/login');
|
|
return;
|
|
}
|
|
if (session?.user && root === 'auth') {
|
|
router.replace('/(tabs)');
|
|
}
|
|
}, [initialized, session?.user, segments, router]);
|
|
|
|
const signIn = useCallback(async (email: string, password: string) => {
|
|
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
if (error) return { error: error.message };
|
|
return {};
|
|
}, []);
|
|
|
|
const signUp = useCallback(
|
|
async (params: {
|
|
email: string;
|
|
password: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
}) => {
|
|
const { error } = await supabase.auth.signUp({
|
|
email: params.email,
|
|
password: params.password,
|
|
options: {
|
|
data: {
|
|
first_name: params.firstName,
|
|
last_name: params.lastName,
|
|
full_name: `${params.firstName} ${params.lastName}`.trim(),
|
|
},
|
|
},
|
|
});
|
|
if (error) return { error: error.message };
|
|
return {};
|
|
},
|
|
[],
|
|
);
|
|
|
|
const signOut = useCallback(async () => {
|
|
await supabase.auth.signOut();
|
|
}, []);
|
|
|
|
const value = useMemo<AuthContextValue>(
|
|
() => ({
|
|
initialized,
|
|
session,
|
|
user: session?.user ?? null,
|
|
signIn,
|
|
signUp,
|
|
signOut,
|
|
}),
|
|
[initialized, session, signIn, signUp, signOut],
|
|
);
|
|
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
}
|
|
|
|
export function useAuth(): AuthContextValue {
|
|
const ctx = useContext(AuthContext);
|
|
if (!ctx) {
|
|
throw new Error('useAuth doit être utilisé dans un AuthProvider');
|
|
}
|
|
return ctx;
|
|
}
|