Spaces:
Sleeping
Sleeping
| import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; | |
| const AuthContext = createContext(null); | |
| export function AuthProvider({ children }) { | |
| const [user, setUser] = useState(null); | |
| const [token, setToken] = useState(localStorage.getItem('gilded-token')); | |
| const [loading, setLoading] = useState(true); | |
| useEffect(() => { | |
| if (!token) { | |
| setLoading(false); | |
| return; | |
| } | |
| fetch('/api/auth/me', { | |
| headers: { Authorization: `Bearer ${token}` }, | |
| }) | |
| .then((res) => { | |
| if (!res.ok) throw new Error('Invalid token'); | |
| return res.json(); | |
| }) | |
| .then((data) => { | |
| setUser(data.user || data); | |
| }) | |
| .catch(() => { | |
| localStorage.removeItem('gilded-token'); | |
| setToken(null); | |
| setUser(null); | |
| }) | |
| .finally(() => setLoading(false)); | |
| }, [token]); | |
| const login = useCallback(async (email, password) => { | |
| const res = await fetch('/api/auth/login', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ email, password }), | |
| }); | |
| if (!res.ok) { | |
| const err = await res.json(); | |
| throw new Error(err.message || 'Login failed'); | |
| } | |
| const data = await res.json(); | |
| localStorage.setItem('gilded-token', data.token); | |
| setToken(data.token); | |
| setUser(data.user); | |
| return data; | |
| }, []); | |
| const register = useCallback(async (username, email, password) => { | |
| const res = await fetch('/api/auth/register', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ username, email, password }), | |
| }); | |
| if (!res.ok) { | |
| const err = await res.json(); | |
| throw new Error(err.message || 'Registration failed'); | |
| } | |
| const data = await res.json(); | |
| localStorage.setItem('gilded-token', data.token); | |
| setToken(data.token); | |
| setUser(data.user); | |
| return data; | |
| }, []); | |
| const logout = useCallback(() => { | |
| localStorage.removeItem('gilded-token'); | |
| setToken(null); | |
| setUser(null); | |
| }, []); | |
| const updateUser = useCallback((data) => { | |
| setUser((prev) => (prev ? { ...prev, ...data } : data)); | |
| }, []); | |
| return ( | |
| <AuthContext.Provider value={{ user, token, loading, login, register, logout, updateUser }}> | |
| {children} | |
| </AuthContext.Provider> | |
| ); | |
| } | |
| export function useAuth() { | |
| const ctx = useContext(AuthContext); | |
| if (!ctx) throw new Error('useAuth must be used within AuthProvider'); | |
| return ctx; | |
| } | |