| import React, { createContext, useContext, useState, useEffect } from 'react'; |
|
|
| const AuthContext = createContext(); |
|
|
| export const useAuth = () => useContext(AuthContext); |
|
|
| import { supabase } from '../supabase'; |
|
|
| export const AuthProvider = ({ children }) => { |
| const [user, setUser] = useState(null); |
| const [token, setToken] = useState(localStorage.getItem('token') || null); |
| const [loading, setLoading] = useState(true); |
| const [authLoading, setAuthLoading] = useState(() => !!sessionStorage.getItem('googleAuthPending')); |
| const [authLoadingMessage, setAuthLoadingMessage] = useState(() => |
| sessionStorage.getItem('googleAuthPending') ? 'Signing in with Google...' : '' |
| ); |
|
|
| useEffect(() => { |
| |
| const savedToken = localStorage.getItem('token'); |
| const savedUser = localStorage.getItem('user'); |
| if (savedToken && savedUser) { |
| setUser(JSON.parse(savedUser)); |
| } |
|
|
| |
| |
| const { data: { subscription } } = supabase.auth.onAuthStateChange( |
| async (event, session) => { |
| if (event === 'SIGNED_IN' && session) { |
| try { |
| |
| |
| const apiUrl = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'; |
| const response = await fetch(`${apiUrl}/api/auth/google`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ |
| email: session.user.email, |
| display_name: session.user.user_metadata?.full_name || session.user.email, |
| }), |
| }); |
| const data = await response.json(); |
|
|
| if (response.ok && data.status === 'success') { |
| setToken(data.data.access_token); |
| setUser(data.data.user); |
| localStorage.setItem('token', data.data.access_token); |
| localStorage.setItem('user', JSON.stringify(data.data.user)); |
| } else { |
| |
| const fallbackUser = { |
| display_name: session.user.user_metadata?.full_name || session.user.email, |
| email: session.user.email, |
| role: 'user', |
| user_id: session.user.id |
| }; |
| setToken(session.access_token); |
| setUser(fallbackUser); |
| localStorage.setItem('token', session.access_token); |
| localStorage.setItem('user', JSON.stringify(fallbackUser)); |
| } |
| } catch { |
| |
| const fallbackUser = { |
| display_name: session.user.user_metadata?.full_name || session.user.email, |
| email: session.user.email, |
| role: 'user', |
| user_id: session.user.id |
| }; |
| setToken(session.access_token); |
| setUser(fallbackUser); |
| localStorage.setItem('token', session.access_token); |
| localStorage.setItem('user', JSON.stringify(fallbackUser)); |
| } |
|
|
| |
| sessionStorage.removeItem('googleAuthPending'); |
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| } |
| |
| |
| |
| } |
| ); |
|
|
| setLoading(false); |
|
|
| return () => { |
| subscription?.unsubscribe(); |
| }; |
| }, []); |
|
|
| const login = async (email, password) => { |
| setAuthLoading(true); |
| setAuthLoadingMessage('Signing in...'); |
| try { |
| const apiUrl = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'; |
| const response = await fetch(`${apiUrl}/api/login`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ email, password }), |
| }); |
| const data = await response.json(); |
|
|
| if (response.ok && data.status === 'success') { |
| setToken(data.data.access_token); |
| setUser(data.data.user); |
| localStorage.setItem('token', data.data.access_token); |
| localStorage.setItem('user', JSON.stringify(data.data.user)); |
| return { success: true }; |
| } else { |
| return { success: false, message: data.message || 'Login failed' }; |
| } |
| } catch (error) { |
| return { success: false, message: 'Network error or server down' }; |
| } finally { |
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| } |
| }; |
|
|
| const register = async (email, password, username, displayName) => { |
| setAuthLoading(true); |
| setAuthLoadingMessage('Creating your account...'); |
| try { |
| const apiUrl = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'; |
| const payload = { email, password, username, display_name: displayName }; |
| const response = await fetch(`${apiUrl}/api/register`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify(payload), |
| }); |
| const data = await response.json(); |
|
|
| if (response.ok && data.status === 'success') { |
| return { success: true }; |
| } else { |
| return { success: false, message: data.message || 'Registration failed' }; |
| } |
| } catch (error) { |
| return { success: false, message: 'Network error or server down' }; |
| } finally { |
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| } |
| }; |
|
|
| const startGoogleLogin = async () => { |
| try { |
| sessionStorage.setItem('googleAuthPending', 'true'); |
| setAuthLoading(true); |
| setAuthLoadingMessage('Signing in with Google...'); |
| const { error } = await supabase.auth.signInWithOAuth({ |
| provider: 'google', |
| options: { redirectTo: window.location.origin + '/' } |
| }); |
| if (error) { |
| sessionStorage.removeItem('googleAuthPending'); |
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| return { success: false, message: error.message }; |
| } |
| |
| return { success: true }; |
| } catch (error) { |
| sessionStorage.removeItem('googleAuthPending'); |
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| return { success: false, message: 'Google authentication failed.' }; |
| } |
| }; |
|
|
| const loginWithGoogle = async (googleToken) => { |
| try { |
| const apiUrl = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'; |
| const response = await fetch(`${apiUrl}/api/auth/google`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ token: googleToken }), |
| }); |
| const data = await response.json(); |
| |
| if (response.ok && data.status === 'success') { |
| setToken(data.data.access_token); |
| setUser(data.data.user); |
| localStorage.setItem('token', data.data.access_token); |
| localStorage.setItem('user', JSON.stringify(data.data.user)); |
| return { success: true }; |
| } else { |
| return { success: false, message: data.message || 'Google Auth failed' }; |
| } |
| } catch (error) { |
| return { success: false, message: 'Network error or server down' }; |
| } |
| }; |
|
|
| const logout = async () => { |
| setAuthLoading(true); |
| setAuthLoadingMessage('Signing out...'); |
| try { |
| if (token) { |
| const apiUrl = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'; |
| await fetch(`${apiUrl}/api/logout`, { |
| method: 'POST', |
| headers: { 'Authorization': `Bearer ${token}` } |
| }); |
| } |
| |
| await supabase.auth.signOut(); |
| } catch (error) { |
| console.error("Error during logout call", error); |
| } finally { |
| setToken(null); |
| setUser(null); |
| |
| |
| const theme = localStorage.getItem('theme'); |
| const introPlayed = sessionStorage.getItem('introPlayed'); |
| |
| |
| localStorage.clear(); |
| sessionStorage.clear(); |
| |
| |
| if (theme) localStorage.setItem('theme', theme); |
| if (introPlayed) sessionStorage.setItem('introPlayed', introPlayed); |
|
|
| setAuthLoading(false); |
| setAuthLoadingMessage(''); |
| } |
| }; |
|
|
| return ( |
| <AuthContext.Provider value={{ user, token, loading, authLoading, authLoadingMessage, login, startGoogleLogin, loginWithGoogle, register, logout }}> |
| {!loading && children} |
| </AuthContext.Provider> |
| ); |
| }; |
|
|