import apiClient from './authApi'; export interface RequestStats { totalRequests: number; openRequests: number; approvedRequests: number; rejectedRequests: number; closedRequests: number; pausedRequests?: number; draftRequests: number; changeFromPrevious: { total: string; open: string; approved: string; rejected: string; }; } export interface TATEfficiency { avgTATCompliance: number; avgCycleTimeHours: number; avgCycleTimeDays: number; delayedWorkflows: number; totalCompleted: number; compliantWorkflows: number; changeFromPrevious: { compliance: string; cycleTime: string; }; } export interface ApproverLoad { pendingActions: number; completedToday: number; completedThisWeek: number; changeFromPrevious: { pending: string; completed: string; }; } export interface EngagementStats { workNotesAdded: number; attachmentsUploaded: number; changeFromPrevious: { workNotes: string; attachments: string; }; } export interface AIInsights { avgConclusionRemarkLength: number; aiSummaryAdoptionPercent: number; totalWithConclusion: number; aiGeneratedCount: number; manualCount: number; changeFromPrevious: { adoption: string; length: string; }; } export interface DashboardKPIs { requestVolume: RequestStats; tatEfficiency: TATEfficiency; approverLoad: ApproverLoad; engagement: EngagementStats; aiInsights: AIInsights; dateRange: { start: string; end: string; label: string; }; } export interface RecentActivity { activityId: string; requestId: string; requestNumber: string; requestTitle: string; type: string; action: string; details?: any; userId: string; userName: string; timestamp: string; priority: string; } export interface CriticalRequest { requestId: string; requestNumber: string; title: string; priority: string; status: string; currentLevel: number; totalLevels: number; submissionDate: string; totalTATHours: number; originalTATHours: number; breachCount: number; isCritical: boolean; approverId?: string | null; approverEmail?: string | null; } export interface AIRemarkUtilization { totalUsage: number; totalEdits: number; editRate: number; monthlyTrends: Array<{ month: string; aiUsage: number; manualEdits: number; }>; } export interface ApproverPerformance { approverId: string; approverName: string; totalApproved: number; approvedCount: number; rejectedCount: number; closedCount: number; tatCompliancePercent: number; avgResponseHours: number; pendingCount: number; withinTatCount: number; breachedCount: number; } export interface UpcomingDeadline { levelId: string; requestId: string; requestNumber: string; requestTitle: string; levelNumber: number; approverName: string; approverEmail: string; tatHours: number; elapsedHours: number; remainingHours: number; tatPercentageUsed: number; levelStartTime: string; priority: string; } export interface DepartmentStats { department: string; totalRequests: number; approved: number; rejected: number; inProgress: number; approvalRate: number; } export interface PriorityDistribution { priority: string; totalCount: number; avgCycleTimeHours: number; approvedCount: number; breachedCount: number; complianceRate: number; } export type DateRange = 'all' | 'today' | 'week' | 'month' | 'quarter' | 'year' | 'last30days' | 'custom'; class DashboardService { /** * Get all KPI metrics */ async getKPIs(dateRange?: DateRange, startDate?: Date, endDate?: Date, viewAsUser?: boolean): Promise { try { const params: any = { dateRange }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } if (viewAsUser) { params.viewAsUser = 'true'; } const response = await apiClient.get('/dashboard/kpis', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch KPIs:', error); throw error; } } /** * Get request statistics */ async getRequestStats( dateRange?: DateRange, startDate?: string, endDate?: string, status?: string, priority?: string, templateType?: string, department?: string, initiator?: string, approver?: string, approverType?: 'current' | 'any', search?: string, slaCompliance?: string, viewAsUser?: boolean ): Promise { try { const params: any = { dateRange }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate; params.endDate = endDate; } // Add filters if (status && status !== 'all') { params.status = status; } if (priority && priority !== 'all') { params.priority = priority; } if (templateType && templateType !== 'all') { params.templateType = templateType; } if (department && department !== 'all') { params.department = department; } if (initiator && initiator !== 'all') { params.initiator = initiator; } if (approver && approver !== 'all') { params.approver = approver; } if (approverType) { params.approverType = approverType; } if (search) { params.search = search; } if (slaCompliance && slaCompliance !== 'all') { params.slaCompliance = slaCompliance; } // Pass viewAsUser flag to tell backend to treat admin as normal user if (viewAsUser) { params.viewAsUser = 'true'; } const response = await apiClient.get('/dashboard/stats/requests', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch request stats:', error); throw error; } } /** * Get TAT efficiency metrics */ async getTATEfficiency(dateRange?: DateRange): Promise { try { const response = await apiClient.get('/dashboard/stats/tat-efficiency', { params: { dateRange } }); return response.data.data; } catch (error) { console.error('Failed to fetch TAT efficiency:', error); throw error; } } /** * Get approver load */ async getApproverLoad(dateRange?: DateRange): Promise { try { const response = await apiClient.get('/dashboard/stats/approver-load', { params: { dateRange } }); return response.data.data; } catch (error) { console.error('Failed to fetch approver load:', error); throw error; } } /** * Get engagement statistics */ async getEngagementStats(dateRange?: DateRange): Promise { try { const response = await apiClient.get('/dashboard/stats/engagement', { params: { dateRange } }); return response.data.data; } catch (error) { console.error('Failed to fetch engagement stats:', error); throw error; } } /** * Get AI insights */ async getAIInsights(dateRange?: DateRange): Promise { try { const response = await apiClient.get('/dashboard/stats/ai-insights', { params: { dateRange } }); return response.data.data; } catch (error) { console.error('Failed to fetch AI insights:', error); throw error; } } /** * Get recent activity feed with pagination */ async getRecentActivity(page: number = 1, limit: number = 10, viewAsUser?: boolean): Promise<{ activities: RecentActivity[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { page, limit }; if (viewAsUser) { params.viewAsUser = 'true'; } const response = await apiClient.get('/dashboard/activity/recent', { params }); return { activities: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch recent activity:', error); throw error; } } /** * Get critical requests with pagination */ async getCriticalRequests(page: number = 1, limit: number = 10, viewAsUser?: boolean): Promise<{ criticalRequests: CriticalRequest[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { page, limit }; if (viewAsUser) { params.viewAsUser = 'true'; } const response = await apiClient.get('/dashboard/requests/critical', { params }); return { criticalRequests: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch critical requests:', error); throw error; } } /** * Get upcoming deadlines with pagination */ async getUpcomingDeadlines(page: number = 1, limit: number = 10, viewAsUser?: boolean): Promise<{ deadlines: UpcomingDeadline[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { page, limit }; if (viewAsUser) { params.viewAsUser = 'true'; } const response = await apiClient.get('/dashboard/deadlines/upcoming', { params }); return { deadlines: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch upcoming deadlines:', error); throw error; } } /** * Get department-wise statistics */ async getDepartmentStats(dateRange?: DateRange, startDate?: Date, endDate?: Date): Promise { try { const params: any = { dateRange }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/stats/by-department', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch department stats:', error); throw error; } } /** * Get priority distribution */ async getPriorityDistribution(dateRange?: DateRange, startDate?: Date, endDate?: Date): Promise { try { const params: any = { dateRange }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/stats/priority-distribution', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch priority distribution:', error); throw error; } } /** * Get AI Remark Utilization with monthly trends */ async getAIRemarkUtilization(dateRange?: DateRange, startDate?: Date, endDate?: Date): Promise { try { const params: any = { dateRange }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/stats/ai-remark-utilization', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch AI remark utilization:', error); throw error; } } /** * Get Approver Performance metrics with pagination * Supports priority and SLA filters for consistent stats behavior */ async getApproverPerformance( dateRange?: DateRange, page: number = 1, limit: number = 10, startDate?: Date, endDate?: Date, priority?: string, slaCompliance?: string ): Promise<{ performance: ApproverPerformance[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { dateRange, page, limit: limit || 10 // Explicitly set limit (default 10 if not provided) }; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } if (priority && priority !== 'all') { params.priority = priority; } if (slaCompliance && slaCompliance !== 'all') { params.slaCompliance = slaCompliance; } const response = await apiClient.get('/dashboard/stats/approver-performance', { params }); return { performance: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch approver performance:', error); throw error; } } /** * Get Request Lifecycle Report */ async getLifecycleReport( page: number = 1, limit: number = 50, dateRange?: DateRange, startDate?: Date, endDate?: Date ): Promise<{ lifecycleData: any[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { page, limit }; if (dateRange) params.dateRange = dateRange; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/reports/lifecycle', { params }); return { lifecycleData: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch lifecycle report:', error); throw error; } } /** * Get enhanced User Activity Log Report */ async getActivityLogReport( page: number = 1, limit: number = 50, dateRange?: DateRange, filterUserId?: string, filterType?: string, filterCategory?: string, filterSeverity?: string, startDate?: Date, endDate?: Date ): Promise<{ activities: any[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { page, limit, filterUserId, filterType, filterCategory, filterSeverity }; if (dateRange) params.dateRange = dateRange; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/reports/activity-log', { params }); return { activities: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch activity log report:', error); throw error; } } /** * Get list of departments (metadata for filtering) */ async getDepartments(): Promise { try { const response = await apiClient.get('/dashboard/metadata/departments'); return response.data.data.departments || []; } catch (error) { console.error('Failed to fetch departments:', error); throw error; } } /** * Get Workflow Aging Report */ async getWorkflowAgingReport( threshold: number = 7, page: number = 1, limit: number = 50, dateRange?: DateRange, startDate?: Date, endDate?: Date ): Promise<{ agingData: any[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { threshold, page, limit }; if (dateRange) params.dateRange = dateRange; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } const response = await apiClient.get('/dashboard/reports/workflow-aging', { params }); return { agingData: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch workflow aging report:', error); throw error; } } /** * Get single approver stats only (dedicated endpoint for performance) * Only respects date, priority, and SLA filters */ async getSingleApproverStats( approverId: string, dateRange?: DateRange, startDate?: Date, endDate?: Date, priority?: string, slaCompliance?: string ): Promise { try { const params: any = { approverId }; if (dateRange) params.dateRange = dateRange; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } if (priority && priority !== 'all') params.priority = priority; if (slaCompliance && slaCompliance !== 'all') params.slaCompliance = slaCompliance; const response = await apiClient.get('/dashboard/stats/single-approver', { params }); return response.data.data; } catch (error) { console.error('Failed to fetch single approver stats:', error); throw error; } } /** * Get requests filtered by approver ID for detailed performance analysis */ async getRequestsByApprover( approverId: string, page: number = 1, limit: number = 50, dateRange?: DateRange, startDate?: Date, endDate?: Date, status?: string, priority?: string, slaCompliance?: string, search?: string ): Promise<{ requests: any[], pagination: { currentPage: number, totalPages: number, totalRecords: number, limit: number } }> { try { const params: any = { approverId, page, limit }; if (dateRange) params.dateRange = dateRange; if (dateRange === 'custom' && startDate && endDate) { params.startDate = startDate.toISOString(); params.endDate = endDate.toISOString(); } if (status) params.status = status; if (priority) params.priority = priority; if (slaCompliance) params.slaCompliance = slaCompliance; if (search) params.search = search; const response = await apiClient.get('/dashboard/requests/by-approver', { params }); return { requests: response.data.data, pagination: response.data.pagination }; } catch (error) { console.error('Failed to fetch requests by approver:', error); throw error; } } } export const dashboardService = new DashboardService(); export default dashboardService;