Re_Figma_Code/src/services/dashboard.service.ts

708 lines
19 KiB
TypeScript

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<DashboardKPIs> {
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<RequestStats> {
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<TATEfficiency> {
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<ApproverLoad> {
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<EngagementStats> {
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<AIInsights> {
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<DepartmentStats[]> {
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<PriorityDistribution[]> {
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<AIRemarkUtilization> {
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<string[]> {
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<ApproverPerformance> {
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;