feat: initialize database and authentication routes in backend

This commit is contained in:
LaurensBartelds committed 2026-04-21 22:51:22 +02:00
1 parent be69db04a5
commit eb013d4978
22 files changed
+1808 -8

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
import { createContext, useContext, useState, useEffect, useCallback } from 'react'
import type { ReactNode } from 'react'
import { apiFetch, setToken, clearToken, isAuthenticated } from '../utils/api'
export interface User {
id: number
email: string
displayName: string
}
interface AuthContextValue {
user: User | null
loading: boolean
login: (email: string, password: string) => Promise<void>
register: (email: string, password: string, displayName: string) => Promise<string>
logout: () => void
refreshUser: () => Promise<void>
}
const AuthContext = createContext<AuthContextValue | null>(null)
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [loading, setLoading] = useState(true)
const refreshUser = useCallback(async () => {
if (!isAuthenticated()) {
setUser(null)
setLoading(false)
return
}
try {
const data = await apiFetch<{ id: number; email: string; displayName: string }>('/api/auth/me')
setUser({ id: data.id, email: data.email, displayName: data.displayName })
} catch {
clearToken()
setUser(null)
} finally {
setLoading(false)
}
}, [])
useEffect(() => {
void refreshUser()
}, [refreshUser])
const login = useCallback(async (email: string, password: string) => {
const data = await apiFetch<{ token: string; user: User }>('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
})
setToken(data.token)
setUser(data.user)
}, [])
const register = useCallback(async (email: string, password: string, displayName: string): Promise<string> => {
const data = await apiFetch<{ message: string }>('/api/auth/register', {
method: 'POST',
body: JSON.stringify({ email, password, displayName }),
})
return data.message
}, [])
const logout = useCallback(() => {
clearToken()
setUser(null)
}, [])
return (
<AuthContext.Provider value={{ user, loading, login, register, logout, refreshUser }}>
{children}
</AuthContext.Provider>
)
}
export function useAuth(): AuthContextValue {
const ctx = useContext(AuthContext)
if (!ctx) throw new Error('useAuth must be used within an AuthProvider')
return ctx
}