- Add TimeSeriesChart component for report trends over time - Add LitterTypeChart component with pie chart for type distribution - Add QuantityChart component with bar chart for quantity aggregation - Update analytics service with new API methods for chart data - Add new types for chart data structures (TimeSeriesDataPoint, LitterTypeDistribution, QuantityAggregation) - Integrate charts into AnalyticsPage with responsive grid layout - Add mock data fallback for development when API is not available - Configure charts for mobile responsiveness - Implement comparison metrics display in time series - Add loading states and empty states for all charts Implements task 11: Data visualization charts Requirements: 5.2, 5.3, 5.4
97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
// Analytics service for API interactions
|
|
import { apiClient } from './api';
|
|
import type { AnalyticsSummary, TimeSeriesDataPoint, LitterTypeDistribution, QuantityAggregation } from '@/types';
|
|
|
|
class AnalyticsService {
|
|
/**
|
|
* Get summary statistics for the analytics dashboard
|
|
*/
|
|
async getSummary(dateRange?: { start: string; end: string }): Promise<AnalyticsSummary> {
|
|
const params = new URLSearchParams();
|
|
|
|
if (dateRange) {
|
|
params.append('startDate', dateRange.start);
|
|
params.append('endDate', dateRange.end);
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
return apiClient.get<AnalyticsSummary>(`/analytics/summary${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get time series data for report trends
|
|
*/
|
|
async getTimeSeries(dateRange?: { start: string; end: string }): Promise<TimeSeriesDataPoint[]> {
|
|
const params = new URLSearchParams();
|
|
|
|
if (dateRange) {
|
|
params.append('startDate', dateRange.start);
|
|
params.append('endDate', dateRange.end);
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
return apiClient.get<TimeSeriesDataPoint[]>(`/analytics/trends${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get litter type distribution data
|
|
*/
|
|
async getLitterTypeDistribution(dateRange?: { start: string; end: string }): Promise<LitterTypeDistribution[]> {
|
|
const params = new URLSearchParams();
|
|
|
|
if (dateRange) {
|
|
params.append('startDate', dateRange.start);
|
|
params.append('endDate', dateRange.end);
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
return apiClient.get<LitterTypeDistribution[]>(`/analytics/litter-types${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get quantity estimation aggregation data
|
|
*/
|
|
async getQuantityAggregation(dateRange?: { start: string; end: string }): Promise<QuantityAggregation[]> {
|
|
const params = new URLSearchParams();
|
|
|
|
if (dateRange) {
|
|
params.append('startDate', dateRange.start);
|
|
params.append('endDate', dateRange.end);
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
return apiClient.get<QuantityAggregation[]>(`/analytics/quantities${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Export analytics data to CSV
|
|
*/
|
|
async exportToCSV(dateRange?: { start: string; end: string }): Promise<Blob> {
|
|
const params = new URLSearchParams();
|
|
|
|
if (dateRange) {
|
|
params.append('startDate', dateRange.start);
|
|
params.append('endDate', dateRange.end);
|
|
}
|
|
|
|
const queryString = params.toString();
|
|
const response = await fetch(
|
|
`${import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/analytics/export${queryString ? `?${queryString}` : ''}`,
|
|
{
|
|
method: 'GET',
|
|
headers: {
|
|
'Accept': 'text/csv',
|
|
},
|
|
}
|
|
);
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Failed to export data');
|
|
}
|
|
|
|
return response.blob();
|
|
}
|
|
}
|
|
|
|
export const analyticsService = new AnalyticsService();
|