← back to Letsbegin
components/AuthProvider.tsx
101 lines
'use client'
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'
import { useRouter, usePathname } from 'next/navigation'
interface AuthContextType {
isAuthenticated: boolean
isLoading: boolean
username: string | null
logout: () => Promise<void>
}
const AuthContext = createContext<AuthContextType>({
isAuthenticated: false,
isLoading: true,
username: null,
logout: async () => {}
})
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }: { children: ReactNode }) {
const [isAuthenticated, setIsAuthenticated] = useState(false)
const [isLoading, setIsLoading] = useState(true)
const [username, setUsername] = useState<string | null>(null)
const router = useRouter()
const pathname = usePathname()
useEffect(() => {
checkAuth()
}, [])
async function checkAuth() {
try {
const res = await fetch('/api/auth/session')
const data = await res.json()
if (data.authenticated) {
setIsAuthenticated(true)
setUsername(data.username || 'admin')
} else {
setIsAuthenticated(false)
setUsername(null)
// Redirect to login if not on login page
if (pathname !== '/login') {
router.push('/login')
}
}
} catch (err) {
console.error('Auth check failed:', err)
setIsAuthenticated(false)
if (pathname !== '/login') {
router.push('/login')
}
} finally {
setIsLoading(false)
}
}
async function logout() {
try {
await fetch('/api/auth/logout', { method: 'POST' })
setIsAuthenticated(false)
setUsername(null)
router.push('/login')
} catch (err) {
console.error('Logout error:', err)
}
}
// Show loading state
if (isLoading) {
return (
<div className="min-h-screen bg-[var(--background)] flex items-center justify-center">
<div className="text-center">
<div className="text-4xl mb-4 animate-pulse">🚀</div>
<div className="text-[var(--foreground-secondary)]">Loading...</div>
</div>
</div>
)
}
// Allow login page to render without auth
if (pathname === '/login') {
return <>{children}</>
}
// Require auth for all other pages
if (!isAuthenticated) {
return null // Will redirect in useEffect
}
return (
<AuthContext.Provider value={{ isAuthenticated, isLoading, username, logout }}>
{children}
</AuthContext.Provider>
)
}