104 lines
2.5 KiB
TypeScript
104 lines
2.5 KiB
TypeScript
'use client';
|
|
|
|
import React, {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
ReactNode,
|
|
} from 'react';
|
|
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, updateProfile, signOut } from 'firebase/auth';
|
|
import { app } from '@/lib/firebase';
|
|
|
|
interface User {
|
|
uid: string;
|
|
email: string | null;
|
|
name: string | null;
|
|
}
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
isLoading: boolean;
|
|
isAuthenticated: boolean;
|
|
login: (email: string, password: string) => Promise<void>;
|
|
register: (email: string, password: string, name: string) => Promise<void>;
|
|
logout: () => Promise<void>;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
interface AuthProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export const AuthProvider = ({ children }: AuthProviderProps) => {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const auth = getAuth(app);
|
|
|
|
useEffect(() => {
|
|
console.log('Setting up auth listener...');
|
|
const unsubscribe = auth.onAuthStateChanged((firebaseUser) => {
|
|
console.log('Auth state changed:', firebaseUser?.email || 'null');
|
|
if (firebaseUser) {
|
|
setUser({
|
|
uid: firebaseUser.uid,
|
|
email: firebaseUser.email,
|
|
name: firebaseUser.displayName,
|
|
});
|
|
} else {
|
|
setUser(null);
|
|
}
|
|
setIsLoading(false);
|
|
});
|
|
|
|
return () => unsubscribe();
|
|
}, [auth]);
|
|
|
|
const login = async (email: string, password: string) => {
|
|
setIsLoading(true);
|
|
try {
|
|
await signInWithEmailAndPassword(auth, email, password);
|
|
} catch (error: any) {
|
|
setIsLoading(false);
|
|
throw new Error(error.message || 'Login failed');
|
|
}
|
|
};
|
|
|
|
const register = async (email: string, password: string, name: string) => {
|
|
setIsLoading(true);
|
|
try {
|
|
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
|
|
await updateProfile(userCredential.user, { displayName: name });
|
|
} catch (error: any) {
|
|
setIsLoading(false);
|
|
throw new Error(error.message || 'Registration failed');
|
|
}
|
|
};
|
|
|
|
const logout = async () => {
|
|
await signOut(auth);
|
|
};
|
|
|
|
const value: AuthContextType = {
|
|
user,
|
|
isLoading,
|
|
isAuthenticated: !!user,
|
|
login,
|
|
register,
|
|
logout,
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={value}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useAuth = () => {
|
|
const ctx = useContext(AuthContext);
|
|
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
|
|
return ctx;
|
|
};
|