390 lines
11 KiB
TypeScript
390 lines
11 KiB
TypeScript
/*
|
|
* File: aiDashboardSlice.ts
|
|
* Description: AI Analysis Dashboard state management slice
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|
|
|
|
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
|
|
import { dashboardAPI } from '../services/dashboardAPI';
|
|
import { logoutUser } from '../../Auth/redux/authActions';
|
|
|
|
// ============================================================================
|
|
// TYPES
|
|
// ============================================================================
|
|
|
|
/**
|
|
* AI Dashboard Statistics Interface
|
|
*
|
|
* Purpose: Defines the structure of AI dashboard statistics data
|
|
*/
|
|
export interface AIDashboardStats {
|
|
total_predictions: number;
|
|
total_patients: number;
|
|
total_feedbacks: number;
|
|
prediction_breakdown: Record<string, number>;
|
|
critical_findings: Record<string, number>;
|
|
midline_shift_stats: Record<string, number>;
|
|
hemorrhage_stats: Record<string, number>;
|
|
mass_lesion_stats: Record<string, number>;
|
|
edema_stats: Record<string, number>;
|
|
fracture_stats: Record<string, number>;
|
|
feedback_analysis: {
|
|
positive: number;
|
|
negative: number;
|
|
total: number;
|
|
};
|
|
hospital_distribution: Record<string, number>;
|
|
time_analysis: {
|
|
today: number;
|
|
this_week: number;
|
|
this_month: number;
|
|
this_year: number;
|
|
};
|
|
urgency_levels: {
|
|
critical: number;
|
|
urgent: number;
|
|
routine: number;
|
|
};
|
|
confidence_scores: {
|
|
high: number;
|
|
medium: number;
|
|
low: number;
|
|
};
|
|
feedback_rate_percentage: number;
|
|
predictions_with_feedback: number;
|
|
predictions_without_feedback: number;
|
|
average_feedback_per_prediction: string;
|
|
critical_case_percentage: number;
|
|
average_confidence_score: number;
|
|
}
|
|
|
|
/**
|
|
* AI Dashboard Summary Interface
|
|
*
|
|
* Purpose: Defines the structure of the AI dashboard summary data
|
|
*/
|
|
export interface AIDashboardSummary {
|
|
total_cases: number;
|
|
critical_cases: number;
|
|
routine_cases: number;
|
|
feedback_coverage: string;
|
|
critical_case_rate: string;
|
|
average_confidence: string;
|
|
}
|
|
|
|
/**
|
|
* Complete AI Dashboard Data Interface
|
|
*
|
|
* Purpose: Defines the complete structure of the AI dashboard API response
|
|
*/
|
|
export interface AIDashboardData {
|
|
success: boolean;
|
|
data: AIDashboardStats;
|
|
summary: AIDashboardSummary;
|
|
message: string;
|
|
}
|
|
|
|
/**
|
|
* AI Dashboard State Interface
|
|
*
|
|
* Purpose: Defines the state structure for AI dashboard
|
|
*/
|
|
export interface AIDashboardState {
|
|
// Dashboard data
|
|
dashboardData: AIDashboardData | null;
|
|
|
|
// Loading states
|
|
isLoading: boolean;
|
|
isRefreshing: boolean;
|
|
|
|
// Error handling
|
|
error: string | null;
|
|
|
|
// Filters and preferences
|
|
selectedTimeRange: 'today' | 'week' | 'month' | 'year';
|
|
selectedHospital: string | null;
|
|
selectedDepartment: string | null;
|
|
|
|
// Last updated timestamp
|
|
lastUpdated: string | null;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ASYNC THUNKS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Fetch AI Dashboard Statistics Async Thunk
|
|
*
|
|
* Purpose: Fetch AI analysis dashboard statistics from API
|
|
*
|
|
* @param token - Authentication token
|
|
* @returns Promise with AI dashboard statistics data or error
|
|
*/
|
|
export const fetchAIDashboardStatistics = createAsyncThunk(
|
|
'aiDashboard/fetchStatistics',
|
|
async (token: string, { rejectWithValue, dispatch }) => {
|
|
try {
|
|
const response :any = await dashboardAPI.getDashboardStatistics(token);
|
|
|
|
// Check for 401 Unauthorized response
|
|
if (response.status === 401) {
|
|
// Dispatch logout action to clear authentication state
|
|
dispatch(logoutUser());
|
|
return rejectWithValue('Session expired. Please login again.');
|
|
}
|
|
|
|
if (response.ok && response.data ) {
|
|
return response.data as AIDashboardData;
|
|
} else {
|
|
return rejectWithValue(response.problem || 'Failed to fetch dashboard statistics');
|
|
}
|
|
} catch (error) {
|
|
return rejectWithValue('Network error occurred while fetching dashboard statistics');
|
|
}
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Refresh AI Dashboard Statistics Async Thunk
|
|
*
|
|
* Purpose: Refresh AI dashboard statistics data
|
|
*
|
|
* @param token - Authentication token
|
|
* @returns Promise with refreshed AI dashboard statistics or error
|
|
*/
|
|
export const refreshAIDashboardStatistics = createAsyncThunk(
|
|
'aiDashboard/refreshStatistics',
|
|
async (token: string, { rejectWithValue, dispatch }) => {
|
|
try {
|
|
const response = await dashboardAPI.getDashboardStatistics(token);
|
|
|
|
// Check for 401 Unauthorized response
|
|
if (response.status === 401) {
|
|
// Dispatch logout action to clear authentication state
|
|
dispatch(logoutUser());
|
|
return rejectWithValue('Session expired. Please login again.');
|
|
}
|
|
|
|
if (response.ok && response.data) {
|
|
return response.data as AIDashboardData;
|
|
} else {
|
|
return rejectWithValue(response.problem || 'Failed to refresh dashboard statistics');
|
|
}
|
|
} catch (error) {
|
|
return rejectWithValue('Network error occurred while refreshing dashboard statistics');
|
|
}
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Fetch Time-based Analysis Async Thunk
|
|
*
|
|
* Purpose: Fetch time-based analysis data for specific time range
|
|
*
|
|
* @param params - Parameters including token and time range
|
|
* @returns Promise with time-based analysis data or error
|
|
*/
|
|
export const fetchTimeBasedAnalysis = createAsyncThunk(
|
|
'aiDashboard/fetchTimeAnalysis',
|
|
async (params: { token: string; timeRange: 'today' | 'week' | 'month' | 'year' }, { rejectWithValue, dispatch }) => {
|
|
try {
|
|
const response = await dashboardAPI.getTimeBasedAnalysis(params.token, params.timeRange);
|
|
|
|
// Check for 401 Unauthorized response
|
|
if (response.status === 401) {
|
|
// Dispatch logout action to clear authentication state
|
|
dispatch(logoutUser());
|
|
return rejectWithValue('Session expired. Please login again.');
|
|
}
|
|
|
|
if (response.ok && response.data) {
|
|
return response.data as AIDashboardData;
|
|
} else {
|
|
return rejectWithValue(response.problem || 'Failed to fetch time-based analysis');
|
|
}
|
|
} catch (error) {
|
|
return rejectWithValue('Network error occurred while fetching time-based analysis');
|
|
}
|
|
}
|
|
);
|
|
|
|
// ============================================================================
|
|
// INITIAL STATE
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Initial AI Dashboard State
|
|
*
|
|
* Purpose: Define the initial state for AI dashboard
|
|
*
|
|
* Features:
|
|
* - AI dashboard statistics data
|
|
* - Loading states for async operations
|
|
* - Error handling and messages
|
|
* - Filter preferences
|
|
* - Last updated tracking
|
|
*/
|
|
const initialState: AIDashboardState = {
|
|
// Dashboard data
|
|
dashboardData: null,
|
|
|
|
// Loading states
|
|
isLoading: false,
|
|
isRefreshing: false,
|
|
|
|
// Error handling
|
|
error: null,
|
|
|
|
// Filters and preferences
|
|
selectedTimeRange: 'today',
|
|
selectedHospital: null,
|
|
selectedDepartment: null,
|
|
|
|
// Last updated timestamp
|
|
lastUpdated: null,
|
|
};
|
|
|
|
// ============================================================================
|
|
// AI DASHBOARD SLICE
|
|
// ============================================================================
|
|
|
|
/**
|
|
* AI Dashboard Slice
|
|
*
|
|
* Purpose: Redux slice for AI dashboard state management
|
|
*
|
|
* Features:
|
|
* - AI dashboard statistics management
|
|
* - Time-based filtering
|
|
* - Hospital and department filtering
|
|
* - Error handling
|
|
* - Loading states
|
|
*/
|
|
const aiDashboardSlice = createSlice({
|
|
name: 'aiDashboard',
|
|
initialState,
|
|
reducers: {
|
|
/**
|
|
* Clear Error Action
|
|
*
|
|
* Purpose: Clear AI dashboard errors
|
|
*/
|
|
clearError: (state) => {
|
|
state.error = null;
|
|
},
|
|
|
|
/**
|
|
* Set Time Range Filter Action
|
|
*
|
|
* Purpose: Set time range filter for statistics
|
|
*/
|
|
setTimeRange: (state, action: PayloadAction<'today' | 'week' | 'month' | 'year'>) => {
|
|
state.selectedTimeRange = action.payload;
|
|
},
|
|
|
|
/**
|
|
* Set Hospital Filter Action
|
|
*
|
|
* Purpose: Set hospital filter for statistics
|
|
*/
|
|
setHospital: (state, action: PayloadAction<string | null>) => {
|
|
state.selectedHospital = action.payload;
|
|
},
|
|
|
|
/**
|
|
* Set Department Filter Action
|
|
*
|
|
* Purpose: Set department filter for statistics
|
|
*/
|
|
setDepartment: (state, action: PayloadAction<string | null>) => {
|
|
state.selectedDepartment = action.payload;
|
|
},
|
|
|
|
/**
|
|
* Update Dashboard Data Action
|
|
*
|
|
* Purpose: Update dashboard data manually
|
|
*/
|
|
updateDashboardData: (state, action: PayloadAction<Partial<AIDashboardData>>) => {
|
|
if (state.dashboardData) {
|
|
state.dashboardData = { ...state.dashboardData, ...action.payload };
|
|
state.lastUpdated = new Date().toLocaleDateString();
|
|
}
|
|
},
|
|
},
|
|
extraReducers: (builder) => {
|
|
// Fetch AI Dashboard Statistics
|
|
builder
|
|
.addCase(fetchAIDashboardStatistics.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchAIDashboardStatistics.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.dashboardData = action.payload;
|
|
state.lastUpdated = new Date().toLocaleDateString();
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchAIDashboardStatistics.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
});
|
|
|
|
// Refresh AI Dashboard Statistics
|
|
builder
|
|
.addCase(refreshAIDashboardStatistics.pending, (state) => {
|
|
state.isRefreshing = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(refreshAIDashboardStatistics.fulfilled, (state, action) => {
|
|
state.isRefreshing = false;
|
|
state.dashboardData = action.payload;
|
|
state.lastUpdated = new Date().toLocaleDateString();
|
|
state.error = null;
|
|
})
|
|
.addCase(refreshAIDashboardStatistics.rejected, (state, action) => {
|
|
state.isRefreshing = false;
|
|
state.error = action.payload as string;
|
|
});
|
|
|
|
// Fetch Time-based Analysis
|
|
builder
|
|
.addCase(fetchTimeBasedAnalysis.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchTimeBasedAnalysis.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.dashboardData = action.payload;
|
|
state.lastUpdated = new Date().toLocaleDateString();
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchTimeBasedAnalysis.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
});
|
|
},
|
|
});
|
|
|
|
// ============================================================================
|
|
// EXPORTS
|
|
// ============================================================================
|
|
|
|
export const {
|
|
clearError,
|
|
setTimeRange,
|
|
setHospital,
|
|
setDepartment,
|
|
updateDashboardData,
|
|
} = aiDashboardSlice.actions;
|
|
|
|
export default aiDashboardSlice.reducer;
|
|
|
|
/*
|
|
* End of File: aiDashboardSlice.ts
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|