179 lines
5.0 KiB
TypeScript
179 lines
5.0 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react'
|
|
import { useRouter } from 'next/navigation'
|
|
import useAuthStore from '../store/authStore'
|
|
|
|
export interface UserStatus {
|
|
email_verified: boolean
|
|
documents_uploaded: boolean
|
|
profile_completed: boolean
|
|
contract_signed: boolean
|
|
is_admin_verified?: boolean
|
|
email_verified_at?: string
|
|
documents_uploaded_at?: string
|
|
profile_completed_at?: string
|
|
contract_signed_at?: string
|
|
}
|
|
|
|
export interface UserStatusResponse {
|
|
success: boolean
|
|
status: UserStatus
|
|
message?: string
|
|
}
|
|
|
|
export const useUserStatus = () => {
|
|
const router = useRouter()
|
|
const [userStatus, setUserStatus] = useState<UserStatus | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [isClient, setIsClient] = useState(false)
|
|
const { accessToken, user } = useAuthStore()
|
|
|
|
// Debug logging
|
|
useEffect(() => {
|
|
console.log('🔍 useUserStatus debug:', {
|
|
isClient,
|
|
hasToken: !!accessToken,
|
|
tokenPrefix: accessToken ? accessToken.substring(0, 20) + '...' : null,
|
|
hasUser: !!user,
|
|
userEmail: user?.email || user?.companyName
|
|
})
|
|
}, [isClient, accessToken, user])
|
|
|
|
// Handle SSR hydration
|
|
useEffect(() => {
|
|
setIsClient(true)
|
|
}, [])
|
|
|
|
const fetchUserStatus = useCallback(async () => {
|
|
if (!isClient) {
|
|
setLoading(false)
|
|
return
|
|
}
|
|
|
|
// If no user, clear status and don't show error
|
|
if (!user) {
|
|
setUserStatus(null)
|
|
setLoading(false)
|
|
setError(null)
|
|
return
|
|
}
|
|
|
|
try {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
// Get current token - it might be null initially
|
|
let currentToken = accessToken
|
|
|
|
// If no token, try to refresh first
|
|
if (!currentToken) {
|
|
console.log('No access token, attempting refresh...')
|
|
const { refreshAuthToken } = useAuthStore.getState()
|
|
const refreshed = await refreshAuthToken()
|
|
if (refreshed) {
|
|
currentToken = useAuthStore.getState().accessToken
|
|
}
|
|
}
|
|
|
|
// If still no token after refresh attempt, this is an auth error
|
|
if (!currentToken) {
|
|
throw new Error('Not authenticated - please log in again')
|
|
}
|
|
|
|
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/status`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Authorization': `Bearer ${currentToken}`,
|
|
'Content-Type': 'application/json'
|
|
}
|
|
})
|
|
|
|
if (response.status === 403) {
|
|
useAuthStore.getState().clearAuth()
|
|
setUserStatus(null)
|
|
setError(null)
|
|
router.push('/suspended')
|
|
return
|
|
}
|
|
|
|
// If 401, try token refresh once
|
|
if (response.status === 401) {
|
|
console.log('Got 401, attempting token refresh...')
|
|
const { refreshAuthToken } = useAuthStore.getState()
|
|
const refreshed = await refreshAuthToken()
|
|
|
|
if (refreshed) {
|
|
const newToken = useAuthStore.getState().accessToken
|
|
if (newToken) {
|
|
// Retry with new token
|
|
const retryResponse = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/user/status`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Authorization': `Bearer ${newToken}`,
|
|
'Content-Type': 'application/json'
|
|
}
|
|
})
|
|
|
|
if (retryResponse.status === 403) {
|
|
useAuthStore.getState().clearAuth()
|
|
setUserStatus(null)
|
|
setError(null)
|
|
router.push('/suspended')
|
|
return
|
|
}
|
|
|
|
if (!retryResponse.ok) {
|
|
throw new Error(`Failed to fetch user status: ${retryResponse.status}`)
|
|
}
|
|
|
|
const retryData: UserStatusResponse = await retryResponse.json()
|
|
if (retryData.success) {
|
|
setUserStatus(retryData.status)
|
|
return
|
|
} else {
|
|
throw new Error(retryData.message || 'Failed to fetch user status')
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new Error('Authentication failed - please log in again')
|
|
}
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch user status: ${response.status}`)
|
|
}
|
|
|
|
const data: UserStatusResponse = await response.json()
|
|
|
|
if (data.success) {
|
|
setUserStatus(data.status)
|
|
} else {
|
|
throw new Error(data.message || 'Failed to fetch user status')
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching user status:', err)
|
|
setError(err instanceof Error ? err.message : 'Unknown error occurred')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}, [isClient, accessToken, user, router])
|
|
|
|
// Fetch status on mount and when auth changes
|
|
useEffect(() => {
|
|
if (isClient) {
|
|
fetchUserStatus()
|
|
}
|
|
}, [isClient, fetchUserStatus])
|
|
|
|
// Refresh function for manual updates
|
|
const refreshStatus = useCallback(() => {
|
|
return fetchUserStatus()
|
|
}, [fetchUserStatus])
|
|
|
|
return {
|
|
userStatus,
|
|
loading,
|
|
error,
|
|
refreshStatus
|
|
}
|
|
} |