File size: 3,154 Bytes
6d4a9a4 7f7aa89 6d4a9a4 7f7aa89 6d4a9a4 7f7aa89 6d4a9a4 7f7aa89 6d4a9a4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | import React, { createContext, useContext, useState, useEffect } from "react";
import { signInWithPopup, signOut as firebaseSignOut } from "firebase/auth";
import { auth, googleProvider } from "@/config/firebase";
import { getCurrentUser, firebaseLogin, requestOTP, verifyOTP, logout as apiLogout } from "@/services/auth";
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [token, setToken] = useState(localStorage.getItem("auth_token"));
useEffect(() => {
// Check if user is already authenticated
if (token) {
checkAuth();
} else {
setLoading(false);
}
}, [token]);
const checkAuth = async () => {
try {
const userData = await getCurrentUser();
setUser(userData);
} catch (error) {
// Token is invalid, clear it
localStorage.removeItem("auth_token");
setToken(null);
setUser(null);
} finally {
setLoading(false);
}
};
const handleFirebaseLogin = async () => {
try {
const result = await signInWithPopup(auth, googleProvider);
const idToken = await result.user.getIdToken();
const response = await firebaseLogin(idToken);
handleAuthCallback(response.token);
} catch (error) {
if (error.code === 'auth/popup-closed' || error.code === 'auth/cancelled-popup-request') {
// User closed popup or cancelled - don't show error
return;
}
console.error("Firebase login error:", error);
throw new Error(error.message || "Firebase authentication failed");
}
};
const handleOTPRequest = async (email) => {
try {
await requestOTP(email);
} catch (error) {
console.error("OTP request error:", error);
throw error;
}
};
const handleOTPVerify = async (email, otp) => {
try {
const response = await verifyOTP(email, otp);
handleAuthCallback(response.token);
} catch (error) {
console.error("OTP verify error:", error);
throw error;
}
};
const handleLogout = async () => {
try {
// Sign out from Firebase if user was using Firebase auth
if (auth.currentUser) {
await firebaseSignOut(auth);
}
await apiLogout();
} catch (error) {
console.error("Logout error:", error);
} finally {
localStorage.removeItem("auth_token");
setToken(null);
setUser(null);
}
};
const handleAuthCallback = (newToken) => {
localStorage.setItem("auth_token", newToken);
setToken(newToken);
checkAuth();
};
const value = {
user,
token,
loading,
firebaseLogin: handleFirebaseLogin,
requestOTP: handleOTPRequest,
verifyOTP: handleOTPVerify,
logout: handleLogout,
handleAuthCallback,
isAuthenticated: !!user,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}
|