Re_Figma_Code/src/pages/Dashboard/hooks/useDashboardData.ts

241 lines
10 KiB
TypeScript

/**
* 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<DashboardKPIs | null>(null);
const [recentActivity, setRecentActivity] = useState<ActivityData[]>([]);
const [criticalRequests, setCriticalRequests] = useState<(CriticalRequest | CriticalAlertData)[]>([]);
const [departmentStats, setDepartmentStats] = useState<DepartmentStats[]>([]);
const [priorityDistribution, setPriorityDistribution] = useState<PriorityDistribution[]>([]);
const [upcomingDeadlines, setUpcomingDeadlines] = useState<UpcomingDeadline[]>([]);
const [aiRemarkUtilization, setAiRemarkUtilization] = useState<AIRemarkUtilization | null>(null);
const [approverPerformance, setApproverPerformance] = useState<ApproverPerformance[]>([]);
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,
};
}