Update project files

This commit is contained in:
2026-07-17 09:48:49 +01:00
parent 0d71e6b7bc
commit cfe7fffce3
27 changed files with 5134 additions and 21 deletions

View File

@@ -0,0 +1,95 @@
import { createContext, useContext, useEffect, useState, useCallback } from 'react'
import { authApi, getStoredSession, profileApi, saveSession } from '../api/client.js'
const AuthContext = createContext(null)
const SITE_ADMIN_ROLES = new Set(['Site Admin', 'Admin'])
export function AuthProvider({ children }) {
const [session, setSession] = useState(null)
const [initializing, setInitializing] = useState(true)
const setCurrentUserProfile = useCallback((profile) => {
setSession(current => {
if (!current) return current
const updated = { ...current, user: profile }
saveSession(updated)
return updated
})
}, [])
const refreshProfile = useCallback(async () => {
const currentSession = await getStoredSession()
if (!currentSession) return null
const profile = await profileApi.getProfile()
setCurrentUserProfile(profile)
return profile
}, [setCurrentUserProfile])
useEffect(() => {
let cancelled = false
async function syncStoredSession() {
const existingSession = await getStoredSession()
if (!existingSession) {
if (!cancelled) setInitializing(false)
return
}
if (!cancelled) setSession(existingSession)
try {
const profile = await profileApi.getProfile()
if (!cancelled) {
const updated = { ...existingSession, user: profile }
await saveSession(updated)
setSession(updated)
}
} catch {
// session may be expired — client will clear it on next 401
} finally {
if (!cancelled) setInitializing(false)
}
}
syncStoredSession()
return () => { cancelled = true }
}, [])
const login = useCallback(async (payload) => {
const data = await authApi.login(payload)
const newSession = { accessToken: data.accessToken, refreshToken: data.refreshToken, user: data.user ?? null }
setSession(newSession)
return data
}, [])
const logout = useCallback(async () => {
await authApi.logout()
setSession(null)
}, [])
const register = useCallback(async (payload) => {
return authApi.register(payload)
}, [])
const user = session?.user ?? null
const userRoles = Array.isArray(user?.roles) ? user.roles : []
const value = {
session,
user,
isAuthenticated: Boolean(session?.accessToken),
isSiteAdmin: userRoles.some(role => SITE_ADMIN_ROLES.has(role)),
initializing,
login,
register,
logout,
refreshProfile,
setCurrentUserProfile,
}
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}
export function useAuth() {
const value = useContext(AuthContext)
if (!value) throw new Error('useAuth must be used inside an AuthProvider.')
return value
}