init
This commit is contained in:
121
mb-app/context/AuthContext.tsx
Normal file
121
mb-app/context/AuthContext.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user