Add auth context for user state management

This commit is contained in:
2026-01-27 22:21:39 +11:00
parent d2f6fbd886
commit edd51e61d3

View File

@@ -0,0 +1,77 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { authService, User } from '../api/auth';
interface AuthContextType {
user: User | null;
token: string | null;
login: (username: string, password: string) => Promise<void>;
logout: () => void;
isLoading: boolean;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [token, setToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// Check for existing token on mount
const storedToken = localStorage.getItem('token');
const storedUser = localStorage.getItem('user');
if (storedToken && storedUser) {
setToken(storedToken);
setUser(JSON.parse(storedUser));
// Verify token is still valid
authService.getCurrentUser()
.then(user => {
setUser(user);
localStorage.setItem('user', JSON.stringify(user));
})
.catch(() => {
// Token invalid, clear storage
localStorage.removeItem('token');
localStorage.removeItem('user');
setToken(null);
setUser(null);
})
.finally(() => setIsLoading(false));
} else {
setIsLoading(false);
}
}, []);
const login = async (username: string, password: string) => {
const response = await authService.login({ username, password });
const userData = await authService.getCurrentUser();
localStorage.setItem('token', response.access_token);
localStorage.setItem('user', JSON.stringify(userData));
setToken(response.access_token);
setUser(userData);
};
const logout = () => {
authService.logout();
setToken(null);
setUser(null);
};
return (
<AuthContext.Provider value={{ user, token, login, logout, isLoading }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};