Spaces:
Sleeping
Sleeping
| 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; | |
| } | |