/** * Hook for fetching and managing dashboard data */ import { useState, useCallback, useRef } from 'react'; import { dashboardService, type DashboardKPIs, type DateRange, type AIRemarkUtilization, type ApproverPerformance, type DepartmentStats, type PriorityDistribution, type UpcomingDeadline, type RecentActivity, type CriticalRequest } from '@/services/dashboard.service'; import { ActivityData } from '@/components/dashboard/ActivityFeedItem'; import type { CriticalAlertData } from '@/components/dashboard/CriticalAlertCard'; interface UseDashboardDataOptions { isAdmin: boolean; viewAsUser?: boolean; // For admin to view as normal user userId?: string; // User ID for filtering - needed to fetch user-initiated requests dateRange: DateRange; customStartDate?: Date; customEndDate?: Date; onPaginationUpdate: { activity: (page: number, totalPages: number, totalRecords: number) => void; critical: (page: number, totalPages: number, totalRecords: number) => void; deadlines: (page: number, totalPages: number, totalRecords: number) => void; approver: (page: number, totalPages: number, totalRecords: number) => void; }; } export function useDashboardData({ isAdmin, viewAsUser = false, userId, // User ID for filtering user-initiated requests dateRange, customStartDate, customEndDate, onPaginationUpdate, }: UseDashboardDataOptions) { const [kpis, setKpis] = useState(null); const [recentActivity, setRecentActivity] = useState([]); const [criticalRequests, setCriticalRequests] = useState<(CriticalRequest | CriticalAlertData)[]>([]); const [departmentStats, setDepartmentStats] = useState([]); const [priorityDistribution, setPriorityDistribution] = useState([]); const [upcomingDeadlines, setUpcomingDeadlines] = useState([]); const [aiRemarkUtilization, setAiRemarkUtilization] = useState(null); const [approverPerformance, setApproverPerformance] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); // Use ref to store latest pagination callbacks to avoid dependency issues const paginationCallbacksRef = useRef(onPaginationUpdate); paginationCallbacksRef.current = onPaginationUpdate; const fetchDashboardData = useCallback(async (showRefreshing = false) => { try { if (showRefreshing) { setRefreshing(true); } else { setLoading(true); } // Fetch common data for all users const commonPromises = [ dashboardService.getKPIs(dateRange, customStartDate, customEndDate, viewAsUser), dashboardService.getRecentActivity(1, 10, viewAsUser), dashboardService.getCriticalRequests(1, 10, viewAsUser), dashboardService.getUpcomingDeadlines(1, 10, viewAsUser) ]; // For normal users (or admin viewing as user): // Fetch user-INITIATED requests stats separately for "My Requests" card // This ensures "My Requests" only shows requests they created, not all requests they're involved in const userInitiatedPromise = (!isAdmin && userId) ? dashboardService.getRequestStats( dateRange, customStartDate?.toISOString(), customEndDate?.toISOString(), undefined, // status undefined, // priority undefined, // templateType undefined, // department userId, // initiator - filter by user's ID to get ONLY their initiated requests undefined, // approver undefined, // approverType undefined, // search undefined, // slaCompliance viewAsUser // viewAsUser - treat as normal user even if admin ) : null; // Fetch admin-only data if user is admin const adminPromises = isAdmin ? [ dashboardService.getDepartmentStats(dateRange, customStartDate, customEndDate), dashboardService.getPriorityDistribution(dateRange, customStartDate, customEndDate), dashboardService.getAIRemarkUtilization(dateRange, customStartDate, customEndDate), dashboardService.getApproverPerformance(dateRange, 1, 10, customStartDate, customEndDate) ] : []; // Fetch all data in parallel const [commonResults, userInitiatedStats, adminResults] = await Promise.all([ Promise.all(commonPromises), userInitiatedPromise, Promise.all(adminPromises) ]); const kpisData = commonResults[0] as DashboardKPIs; const activityResult = commonResults[1] as { activities: RecentActivity[]; pagination: { currentPage: number; totalPages: number; totalRecords: number; limit: number } }; const criticalResult = commonResults[2] as { criticalRequests: CriticalRequest[]; pagination: { currentPage: number; totalPages: number; totalRecords: number; limit: number } }; const deadlinesResult = commonResults[3] as { deadlines: UpcomingDeadline[]; pagination: { currentPage: number; totalPages: number; totalRecords: number; limit: number } }; // For normal users: Override requestVolume with user-initiated requests only // This makes "My Requests" show only requests they created // Other KPIs (approverLoad, etc.) remain as-is since they need all involved requests if (!isAdmin && userInitiatedStats) { kpisData.requestVolume = userInitiatedStats; } setKpis(kpisData); setRecentActivity(activityResult.activities); paginationCallbacksRef.current.activity( activityResult.pagination.currentPage, activityResult.pagination.totalPages, activityResult.pagination.totalRecords ); setCriticalRequests(criticalResult.criticalRequests); paginationCallbacksRef.current.critical( criticalResult.pagination.currentPage, criticalResult.pagination.totalPages, criticalResult.pagination.totalRecords ); setUpcomingDeadlines(deadlinesResult.deadlines); paginationCallbacksRef.current.deadlines( deadlinesResult.pagination.currentPage, deadlinesResult.pagination.totalPages, deadlinesResult.pagination.totalRecords ); // Only set admin-specific data if user is admin if (isAdmin && adminResults.length >= 4) { const deptStats = adminResults[0] as DepartmentStats[]; const priorityDist = adminResults[1] as PriorityDistribution[]; const aiUtilization = adminResults[2] as AIRemarkUtilization; const approverResult = adminResults[3] as { performance: ApproverPerformance[]; pagination: { currentPage: number; totalPages: number; totalRecords: number; limit: number } }; setDepartmentStats(deptStats); setPriorityDistribution(priorityDist); setAiRemarkUtilization(aiUtilization); setApproverPerformance(approverResult.performance); paginationCallbacksRef.current.approver( approverResult.pagination.currentPage, approverResult.pagination.totalPages, approverResult.pagination.totalRecords ); } else if (!isAdmin) { // Reset admin-specific data for normal users setDepartmentStats([]); setPriorityDistribution([]); setAiRemarkUtilization(null); setApproverPerformance([]); } } catch (error) { console.error('Failed to fetch dashboard data:', error); } finally { setLoading(false); setRefreshing(false); } }, [isAdmin, viewAsUser, userId, dateRange, customStartDate, customEndDate]); // Fetch individual data with pagination const fetchRecentActivities = useCallback(async (page: number = 1) => { try { const result = await dashboardService.getRecentActivity(page, 10, viewAsUser); setRecentActivity(result.activities); paginationCallbacksRef.current.activity( result.pagination.currentPage, result.pagination.totalPages, result.pagination.totalRecords ); } catch (error) { console.error('Failed to fetch recent activities:', error); } }, [viewAsUser]); const fetchCriticalRequests = useCallback(async (page: number = 1) => { try { const result = await dashboardService.getCriticalRequests(page, 10, viewAsUser); setCriticalRequests(result.criticalRequests); paginationCallbacksRef.current.critical( result.pagination.currentPage, result.pagination.totalPages, result.pagination.totalRecords ); } catch (error) { console.error('Failed to fetch critical requests:', error); } }, [viewAsUser]); const fetchUpcomingDeadlines = useCallback(async (page: number = 1) => { try { const result = await dashboardService.getUpcomingDeadlines(page, 10, viewAsUser); setUpcomingDeadlines(result.deadlines); paginationCallbacksRef.current.deadlines( result.pagination.currentPage, result.pagination.totalPages, result.pagination.totalRecords ); } catch (error) { console.error('Failed to fetch upcoming deadlines:', error); } }, [viewAsUser]); const fetchApproverPerformance = useCallback(async (page: number = 1) => { try { const result = await dashboardService.getApproverPerformance(dateRange, page, 10, customStartDate, customEndDate); setApproverPerformance(result.performance); paginationCallbacksRef.current.approver( result.pagination.currentPage, result.pagination.totalPages, result.pagination.totalRecords ); } catch (error) { console.error('Failed to fetch approver performance:', error); } }, [dateRange, customStartDate, customEndDate]); return { kpis, recentActivity, criticalRequests, departmentStats, priorityDistribution, upcomingDeadlines, aiRemarkUtilization, approverPerformance, loading, refreshing, fetchDashboardData, fetchRecentActivities, fetchCriticalRequests, fetchUpcomingDeadlines, fetchApproverPerformance, }; }