195 lines
5.1 KiB
TypeScript
195 lines
5.1 KiB
TypeScript
|
|
"use client"
|
||
|
|
|
||
|
|
import { useState, useEffect } from "react"
|
||
|
|
import { useRouter } from "next/navigation"
|
||
|
|
import { API_CONFIG } from "@/lib/config"
|
||
|
|
import apiClient from "@/lib/api-client"
|
||
|
|
|
||
|
|
interface User {
|
||
|
|
id: string
|
||
|
|
name: string
|
||
|
|
email: string
|
||
|
|
is_active: boolean
|
||
|
|
created_at: string
|
||
|
|
updated_at: string
|
||
|
|
department_response?: any
|
||
|
|
}
|
||
|
|
|
||
|
|
interface Role {
|
||
|
|
id: string
|
||
|
|
name: string
|
||
|
|
code: string
|
||
|
|
}
|
||
|
|
|
||
|
|
interface LoginResponse {
|
||
|
|
success: boolean
|
||
|
|
data: {
|
||
|
|
token: string
|
||
|
|
expires_at: string
|
||
|
|
user: User
|
||
|
|
roles: Role[]
|
||
|
|
permissions: any[]
|
||
|
|
departments: any
|
||
|
|
}
|
||
|
|
errors: any
|
||
|
|
}
|
||
|
|
|
||
|
|
export function useAuth() {
|
||
|
|
const [user, setUser] = useState<User | null>(null)
|
||
|
|
const [loading, setLoading] = useState(true)
|
||
|
|
const [token, setToken] = useState<string | null>(null)
|
||
|
|
const [roles, setRoles] = useState<Role[]>([])
|
||
|
|
const router = useRouter()
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
checkAuth()
|
||
|
|
}, [])
|
||
|
|
|
||
|
|
const checkAuth = async () => {
|
||
|
|
try {
|
||
|
|
const storedToken = localStorage.getItem("auth_token")
|
||
|
|
const storedUser = localStorage.getItem("auth_user")
|
||
|
|
const storedRoles = localStorage.getItem("auth_roles")
|
||
|
|
|
||
|
|
if (!storedToken || !storedUser) {
|
||
|
|
setLoading(false)
|
||
|
|
// Redirect to login page when no session exists
|
||
|
|
router.push("/login")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set the stored data
|
||
|
|
setToken(storedToken)
|
||
|
|
setUser(JSON.parse(storedUser))
|
||
|
|
if (storedRoles) {
|
||
|
|
const parsedRoles = JSON.parse(storedRoles)
|
||
|
|
// console.log('🔄 Loading roles from localStorage:', parsedRoles)
|
||
|
|
setRoles(parsedRoles)
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Auth check failed:", error)
|
||
|
|
// Clear invalid data and redirect to login
|
||
|
|
localStorage.removeItem("auth_token")
|
||
|
|
localStorage.removeItem("auth_user")
|
||
|
|
localStorage.removeItem("auth_roles")
|
||
|
|
setUser(null)
|
||
|
|
setToken(null)
|
||
|
|
setRoles([])
|
||
|
|
router.push("/login")
|
||
|
|
} finally {
|
||
|
|
setLoading(false)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const login = async (email: string, password: string) => {
|
||
|
|
try {
|
||
|
|
console.log('Attempting login with Axios...')
|
||
|
|
|
||
|
|
const response = await apiClient.post<LoginResponse>('/api/v1/auth/login', {
|
||
|
|
email,
|
||
|
|
password,
|
||
|
|
})
|
||
|
|
|
||
|
|
console.log('Login successful:', response.data)
|
||
|
|
|
||
|
|
if (response.data.success && response.data.data) {
|
||
|
|
const { token, user, roles, expires_at } = response.data.data
|
||
|
|
|
||
|
|
// Store session data in localStorage
|
||
|
|
localStorage.setItem("auth_token", token)
|
||
|
|
localStorage.setItem("auth_user", JSON.stringify(user))
|
||
|
|
localStorage.setItem("auth_roles", JSON.stringify(roles))
|
||
|
|
localStorage.setItem("auth_expires_at", expires_at)
|
||
|
|
|
||
|
|
// console.log('💾 Storing roles in localStorage:', roles)
|
||
|
|
|
||
|
|
// Update state
|
||
|
|
setToken(token)
|
||
|
|
setUser(user)
|
||
|
|
setRoles(roles)
|
||
|
|
|
||
|
|
return { success: true, user, roles, token }
|
||
|
|
} else {
|
||
|
|
return { success: false, message: response.data.errors || "Login failed" }
|
||
|
|
}
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("Login error:", error)
|
||
|
|
|
||
|
|
// Handle different types of errors
|
||
|
|
if (error.response) {
|
||
|
|
// Server responded with error status
|
||
|
|
const errorMessage = error.response.data?.errors || `Server error: ${error.response.status}`
|
||
|
|
return { success: false, message: errorMessage }
|
||
|
|
} else if (error.request) {
|
||
|
|
// Request was made but no response received
|
||
|
|
return { success: false, message: "No response from server. Please check your connection." }
|
||
|
|
} else {
|
||
|
|
// Something else happened
|
||
|
|
return { success: false, message: "Terjadi kesalahan sistem" }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const logout = async () => {
|
||
|
|
try {
|
||
|
|
// Call external logout endpoint if available
|
||
|
|
if (token) {
|
||
|
|
await apiClient.post('/api/v1/auth/logout', {}, {
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Logout error:", error)
|
||
|
|
// Continue with logout even if API call fails
|
||
|
|
} finally {
|
||
|
|
// Clear all session data
|
||
|
|
localStorage.removeItem("auth_token")
|
||
|
|
localStorage.removeItem("auth_user")
|
||
|
|
localStorage.removeItem("auth_roles")
|
||
|
|
localStorage.removeItem("auth_expires_at")
|
||
|
|
|
||
|
|
// Clear state
|
||
|
|
setToken(null)
|
||
|
|
setUser(null)
|
||
|
|
setRoles([])
|
||
|
|
|
||
|
|
// Redirect to login
|
||
|
|
router.push("/login")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const isAuthenticated = !!user && !!token
|
||
|
|
const isAdmin = roles.some(role => role.code === "superadmin" || role.code === "admin")
|
||
|
|
const isVoter = roles.some(role => role.code === "voter")
|
||
|
|
const isSuperAdmin = roles.some(role => role.code === "superadmin")
|
||
|
|
|
||
|
|
// Debug logging for role checking (commented out to reduce console spam)
|
||
|
|
// console.log('🔐 Auth Debug:', {
|
||
|
|
// user: !!user,
|
||
|
|
// token: !!token,
|
||
|
|
// rolesCount: roles.length,
|
||
|
|
// roles: roles,
|
||
|
|
// isAuthenticated,
|
||
|
|
// isAdmin,
|
||
|
|
// isVoter,
|
||
|
|
// isSuperAdmin
|
||
|
|
// })
|
||
|
|
|
||
|
|
return {
|
||
|
|
user,
|
||
|
|
token,
|
||
|
|
roles,
|
||
|
|
loading,
|
||
|
|
isAuthenticated,
|
||
|
|
isAdmin,
|
||
|
|
isVoter,
|
||
|
|
isSuperAdmin,
|
||
|
|
login,
|
||
|
|
logout,
|
||
|
|
checkAuth,
|
||
|
|
}
|
||
|
|
}
|