feat: Add Auth Service with JWT authentication

This commit is contained in:
Apple
2025-11-26 11:47:00 -08:00
parent 2c4eb7d432
commit 5aaf6cbf21
23 changed files with 3522 additions and 26 deletions

View File

@@ -0,0 +1,86 @@
'use client'
import { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react'
import { User, getStoredUser, getMe, login as authLogin, logout as authLogout, register as authRegister, isAuthenticated } from '@/lib/auth'
interface AuthContextType {
user: User | null
isLoading: boolean
isAuthenticated: boolean
login: (email: string, password: string) => Promise<void>
register: (email: string, password: string, displayName?: string) => Promise<void>
logout: () => Promise<void>
refreshUser: () => Promise<void>
}
const AuthContext = createContext<AuthContextType | undefined>(undefined)
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState(true)
const refreshUser = useCallback(async () => {
try {
const userData = await getMe()
setUser(userData)
} catch {
setUser(null)
}
}, [])
useEffect(() => {
// Check for stored user on mount
const storedUser = getStoredUser()
if (storedUser) {
setUser(storedUser)
}
// Verify token and refresh user data
if (isAuthenticated()) {
refreshUser().finally(() => setIsLoading(false))
} else {
setIsLoading(false)
}
}, [refreshUser])
const login = async (email: string, password: string) => {
const response = await authLogin(email, password)
setUser(response.user)
}
const register = async (email: string, password: string, displayName?: string) => {
await authRegister(email, password, displayName)
// Auto-login after registration
await login(email, password)
}
const logout = async () => {
await authLogout()
setUser(null)
}
return (
<AuthContext.Provider
value={{
user,
isLoading,
isAuthenticated: !!user,
login,
register,
logout,
refreshUser
}}
>
{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
}