Readur/frontend/src/contexts/AuthContext.tsx

84 lines
2.2 KiB
TypeScript

import React, { createContext, useContext, useEffect, useState } from 'react'
import { api } from '../services/api'
interface User {
id: string
username: string
email: string
role: 'Admin' | 'User'
}
interface AuthContextType {
user: User | null
loading: boolean
login: (username: string, password: string) => Promise<void>
register: (username: string, email: string, password: string) => Promise<void>
logout: () => void
}
export const AuthContext = createContext<AuthContextType | undefined>(undefined)
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
const token = localStorage.getItem('token')
if (token) {
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
fetchUser()
} else {
setLoading(false)
}
}, [])
const fetchUser = async () => {
try {
const response = await api.get('/auth/me')
setUser(response.data)
} catch (error) {
localStorage.removeItem('token')
delete api.defaults.headers.common['Authorization']
} finally {
setLoading(false)
}
}
const login = async (username: string, password: string) => {
const response = await api.post('/auth/login', { username, password })
const { token, user: userData } = response.data
localStorage.setItem('token', token)
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
setUser(userData)
}
const register = async (username: string, email: string, password: string) => {
await api.post('/auth/register', { username, email, password })
await login(username, password)
}
const logout = () => {
localStorage.removeItem('token')
delete api.defaults.headers.common['Authorization']
setUser(null)
}
const value = {
user,
loading,
login,
register,
logout,
}
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}
export function useAuth() {
const context = useContext(AuthContext)
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider')
}
return context
}