login system

This commit is contained in:
2026-06-02 11:31:11 -04:00
parent f6bced78f3
commit a1b120076b
17 changed files with 579 additions and 27 deletions
+74
View File
@@ -0,0 +1,74 @@
import { createContext, createElement, useContext, useEffect, useMemo, useState } from 'react'
import { getMe, getStoredToken, login as loginApi, setStoredToken } from '../lib/api'
const AuthContext = createContext(null)
export function AuthProvider({ children }) {
const [user, setUser] = useState(null)
const [isReady, setIsReady] = useState(false)
useEffect(() => {
async function initializeAuth() {
const token = getStoredToken()
if (!token) {
setIsReady(true)
return
}
try {
const data = await getMe()
setUser(data?.user ?? null)
} catch {
setStoredToken(null)
setUser(null)
} finally {
setIsReady(true)
}
}
initializeAuth()
}, [])
useEffect(() => {
function handleUnauthorized() {
setUser(null)
}
window.addEventListener('auth:unauthorized', handleUnauthorized)
return () => window.removeEventListener('auth:unauthorized', handleUnauthorized)
}, [])
async function login(username, password) {
const data = await loginApi({ username, password })
setStoredToken(data?.token)
setUser(data?.user ?? null)
return data?.user ?? null
}
function logout() {
setStoredToken(null)
setUser(null)
}
const value = useMemo(
() => ({
user,
isReady,
isAuthenticated: Boolean(user),
isAdmin: user?.role === 'admin',
login,
logout,
}),
[user, isReady]
)
return createElement(AuthContext.Provider, { value }, children)
}
export function useAuth() {
const context = useContext(AuthContext)
if (!context) {
throw new Error('useAuth must be used inside AuthProvider')
}
return context
}