- Add comprehensive API client methods for all advanced analytics endpoints - Create CircadianRhythmCard component for sleep pattern visualization - Create AnomalyAlertsPanel for anomaly detection and alerts - Create GrowthPercentileChart with WHO/CDC percentiles - Create CorrelationInsights for activity correlations - Create TrendAnalysisChart with predictions - Add advanced analytics page with all new components - Add UI component library (shadcn/ui) setup - Add navigation link to advanced analytics from insights page All advanced analytics features are now accessible from the frontend UI.
537 lines
13 KiB
TypeScript
537 lines
13 KiB
TypeScript
import { apiClient } from './client';
|
|
|
|
export interface SleepPattern {
|
|
averageDuration: number;
|
|
averageBedtime: string;
|
|
averageWakeTime: string;
|
|
nightWakings: number;
|
|
napCount: number;
|
|
consistency: number;
|
|
trend: 'improving' | 'stable' | 'declining';
|
|
}
|
|
|
|
export interface FeedingPattern {
|
|
averageInterval: number;
|
|
averageDuration: number;
|
|
totalFeedings: number;
|
|
feedingMethod: Record<string, number>;
|
|
consistency: number;
|
|
trend: 'increasing' | 'stable' | 'decreasing';
|
|
}
|
|
|
|
export interface DiaperPattern {
|
|
wetDiapersPerDay: number;
|
|
dirtyDiapersPerDay: number;
|
|
averageInterval: number;
|
|
isHealthy: boolean;
|
|
notes: string;
|
|
}
|
|
|
|
export interface GrowthSpurtDetection {
|
|
isLikelyGrowthSpurt: boolean;
|
|
confidence: number;
|
|
indicators: string[];
|
|
expectedDuration: string;
|
|
recommendations: string[];
|
|
}
|
|
|
|
export interface PatternInsights {
|
|
sleep: SleepPattern | null;
|
|
feeding: FeedingPattern | null;
|
|
diaper: DiaperPattern | null;
|
|
growthSpurt: GrowthSpurtDetection | null;
|
|
recommendations: string[];
|
|
concernsDetected: string[];
|
|
}
|
|
|
|
export interface SleepPrediction {
|
|
nextNapTime: Date | null;
|
|
nextNapConfidence: number;
|
|
nextBedtime: Date | null;
|
|
bedtimeConfidence: number;
|
|
optimalWakeWindows: number[];
|
|
reasoning: string;
|
|
}
|
|
|
|
export interface FeedingPrediction {
|
|
nextFeedingTime: Date | null;
|
|
confidence: number;
|
|
expectedInterval: number;
|
|
reasoning: string;
|
|
}
|
|
|
|
export interface PredictionInsights {
|
|
sleep: SleepPrediction;
|
|
feeding: FeedingPrediction;
|
|
generatedAt: Date;
|
|
}
|
|
|
|
export interface WeeklyReport {
|
|
childId: string;
|
|
weekStart: Date;
|
|
weekEnd: Date;
|
|
summary: {
|
|
totalFeedings: number;
|
|
averageFeedingsPerDay: number;
|
|
totalSleepHours: number;
|
|
averageSleepHoursPerDay: number;
|
|
totalDiapers: number;
|
|
averageDiapersPerDay: number;
|
|
};
|
|
dailyData: Array<{
|
|
date: Date;
|
|
feedings: number;
|
|
sleepHours: number;
|
|
diapers: number;
|
|
}>;
|
|
trends: {
|
|
feedingTrend: 'increasing' | 'stable' | 'decreasing';
|
|
sleepTrend: 'improving' | 'stable' | 'declining';
|
|
};
|
|
highlights: string[];
|
|
}
|
|
|
|
export interface MonthlyReport {
|
|
childId: string;
|
|
month: Date;
|
|
summary: {
|
|
totalFeedings: number;
|
|
totalSleepHours: number;
|
|
totalDiapers: number;
|
|
averageFeedingsPerDay: number;
|
|
averageSleepHoursPerDay: number;
|
|
averageDiapersPerDay: number;
|
|
};
|
|
weeklyData: Array<{
|
|
weekStart: Date;
|
|
feedings: number;
|
|
sleepHours: number;
|
|
diapers: number;
|
|
}>;
|
|
milestones: string[];
|
|
trends: string[];
|
|
}
|
|
|
|
// Advanced Analytics Interfaces
|
|
export interface CircadianRhythm {
|
|
sleepPhaseShift: number;
|
|
consistency: number;
|
|
optimalBedtime: string;
|
|
optimalWakeTime: string;
|
|
chronotype: 'early_bird' | 'night_owl' | 'typical';
|
|
melatoninOnset: string;
|
|
recommendedSchedule: {
|
|
wakeTime: string;
|
|
morningNap?: { start: string; duration: number };
|
|
afternoonNap?: { start: string; duration: number };
|
|
bedtime: string;
|
|
totalSleepTarget: number;
|
|
};
|
|
}
|
|
|
|
export interface AnomalyDetection {
|
|
anomalies: Array<{
|
|
activityId: string;
|
|
type: string;
|
|
timestamp: Date;
|
|
severity: 'low' | 'medium' | 'high';
|
|
description: string;
|
|
deviation: number;
|
|
}>;
|
|
alerts: Array<{
|
|
type: string;
|
|
severity: 'info' | 'warning' | 'critical';
|
|
message: string;
|
|
recommendations: string[];
|
|
}>;
|
|
confidenceScore: number;
|
|
}
|
|
|
|
export interface PatternCluster {
|
|
clusterId: string;
|
|
label: string;
|
|
activities: any[];
|
|
centroid: {
|
|
averageTime: string;
|
|
averageDuration: number;
|
|
characteristics: Record<string, any>;
|
|
};
|
|
confidence: number;
|
|
}
|
|
|
|
export interface CorrelationAnalysis {
|
|
feedingSleepCorrelation: number;
|
|
activityDiaperCorrelation: number;
|
|
sleepMoodCorrelation?: number;
|
|
insights: string[];
|
|
}
|
|
|
|
export interface TrendAnalysis {
|
|
shortTermTrend: {
|
|
direction: 'improving' | 'stable' | 'declining';
|
|
slope: number;
|
|
confidence: number;
|
|
r2Score: number;
|
|
changePercent: number;
|
|
};
|
|
mediumTermTrend: {
|
|
direction: 'improving' | 'stable' | 'declining';
|
|
slope: number;
|
|
confidence: number;
|
|
r2Score: number;
|
|
changePercent: number;
|
|
};
|
|
longTermTrend: {
|
|
direction: 'improving' | 'stable' | 'declining';
|
|
slope: number;
|
|
confidence: number;
|
|
r2Score: number;
|
|
changePercent: number;
|
|
};
|
|
seasonalPatterns?: Array<{
|
|
type: 'weekly' | 'monthly';
|
|
pattern: string;
|
|
strength: number;
|
|
}>;
|
|
prediction: {
|
|
next7Days: Array<{
|
|
date: Date;
|
|
predictedValue: number;
|
|
confidenceInterval: { lower: number; upper: number };
|
|
}>;
|
|
confidence: number;
|
|
factors: string[];
|
|
};
|
|
}
|
|
|
|
export interface GrowthPercentile {
|
|
weight?: {
|
|
value: number;
|
|
percentile: number;
|
|
zScore: number;
|
|
interpretation: string;
|
|
};
|
|
height?: {
|
|
value: number;
|
|
percentile: number;
|
|
zScore: number;
|
|
interpretation: string;
|
|
};
|
|
headCircumference?: {
|
|
value: number;
|
|
percentile: number;
|
|
zScore: number;
|
|
interpretation: string;
|
|
};
|
|
bmi?: {
|
|
value: number;
|
|
percentile: number;
|
|
zScore: number;
|
|
interpretation: string;
|
|
};
|
|
}
|
|
|
|
export interface GrowthAnalysis {
|
|
currentPercentiles: GrowthPercentile;
|
|
growthVelocity: {
|
|
weightVelocity?: {
|
|
value: number;
|
|
unit: string;
|
|
percentile: number;
|
|
};
|
|
heightVelocity?: {
|
|
value: number;
|
|
unit: string;
|
|
percentile: number;
|
|
};
|
|
interpretation: string;
|
|
concerns: string[];
|
|
};
|
|
growthCurve: {
|
|
measurements: Array<{
|
|
date: Date;
|
|
weight?: number;
|
|
height?: number;
|
|
headCircumference?: number;
|
|
}>;
|
|
percentileCurves: {
|
|
weight: Record<string, number[]>;
|
|
height: Record<string, number[]>;
|
|
headCircumference: Record<string, number[]>;
|
|
};
|
|
};
|
|
projections: {
|
|
threeMonths: GrowthPercentile;
|
|
sixMonths: GrowthPercentile;
|
|
confidence: number;
|
|
};
|
|
recommendations: string[];
|
|
alerts: Array<{
|
|
type: string;
|
|
severity: 'low' | 'medium' | 'high';
|
|
message: string;
|
|
action: string;
|
|
}>;
|
|
}
|
|
|
|
export interface AdvancedAnalyticsDashboard {
|
|
circadianRhythm: CircadianRhythm;
|
|
anomalies: AnomalyDetection;
|
|
correlations: CorrelationAnalysis;
|
|
growthAnalysis: GrowthAnalysis;
|
|
trends: Record<string, TrendAnalysis>;
|
|
clusters: Record<string, PatternCluster[]>;
|
|
}
|
|
|
|
export const analyticsApi = {
|
|
// Get pattern insights
|
|
getInsights: async (childId: string, days: number = 7): Promise<PatternInsights> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/insights/${childId}`, {
|
|
params: { days },
|
|
});
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get predictions
|
|
getPredictions: async (childId: string): Promise<PredictionInsights> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/predictions/${childId}`);
|
|
const data = response.data.data;
|
|
|
|
// Convert date strings to Date objects
|
|
return {
|
|
...data,
|
|
generatedAt: new Date(data.generatedAt),
|
|
sleep: {
|
|
...data.sleep,
|
|
nextNapTime: data.sleep.nextNapTime ? new Date(data.sleep.nextNapTime) : null,
|
|
nextBedtime: data.sleep.nextBedtime ? new Date(data.sleep.nextBedtime) : null,
|
|
},
|
|
feeding: {
|
|
...data.feeding,
|
|
nextFeedingTime: data.feeding.nextFeedingTime ? new Date(data.feeding.nextFeedingTime) : null,
|
|
},
|
|
};
|
|
},
|
|
|
|
// Get weekly report
|
|
getWeeklyReport: async (childId: string, startDate?: Date): Promise<WeeklyReport> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/reports/${childId}/weekly`, {
|
|
params: startDate ? { startDate: startDate.toISOString() } : {},
|
|
});
|
|
const data = response.data.data;
|
|
|
|
// Convert date strings
|
|
return {
|
|
...data,
|
|
weekStart: new Date(data.weekStart),
|
|
weekEnd: new Date(data.weekEnd),
|
|
dailyData: data.dailyData.map((d: any) => ({
|
|
...d,
|
|
date: new Date(d.date),
|
|
})),
|
|
};
|
|
},
|
|
|
|
// Get monthly report
|
|
getMonthlyReport: async (childId: string, month?: Date): Promise<MonthlyReport> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/reports/${childId}/monthly`, {
|
|
params: month ? { month: month.toISOString() } : {},
|
|
});
|
|
const data = response.data.data;
|
|
|
|
// Convert date strings
|
|
return {
|
|
...data,
|
|
month: new Date(data.month),
|
|
weeklyData: data.weeklyData.map((w: any) => ({
|
|
...w,
|
|
weekStart: new Date(w.weekStart),
|
|
})),
|
|
};
|
|
},
|
|
|
|
// Export data
|
|
exportData: async (
|
|
childId: string,
|
|
format: 'json' | 'csv' | 'pdf',
|
|
startDate?: Date,
|
|
endDate?: Date,
|
|
): Promise<Blob> => {
|
|
const params: any = { format };
|
|
if (startDate) params.startDate = startDate.toISOString();
|
|
if (endDate) params.endDate = endDate.toISOString();
|
|
|
|
const response = await apiClient.get(`/api/v1/analytics/export/${childId}`, {
|
|
params,
|
|
responseType: format === 'json' ? 'json' : 'blob',
|
|
});
|
|
|
|
if (format === 'json') {
|
|
// Convert JSON to Blob
|
|
const jsonStr = JSON.stringify(response.data, null, 2);
|
|
return new Blob([jsonStr], { type: 'application/json' });
|
|
}
|
|
|
|
return response.data;
|
|
},
|
|
|
|
// Compare children
|
|
compareChildren: async (
|
|
childIds: string[],
|
|
metric: ComparisonMetric,
|
|
startDate: string,
|
|
endDate: string,
|
|
): Promise<any> => {
|
|
const response = await apiClient.get('/api/v1/analytics/compare', {
|
|
params: {
|
|
childIds: childIds.join(','),
|
|
metric,
|
|
startDate,
|
|
endDate,
|
|
},
|
|
});
|
|
return response.data.data;
|
|
},
|
|
|
|
// Advanced Analytics Methods
|
|
|
|
// Get circadian rhythm analysis
|
|
getCircadianRhythm: async (childId: string, days: number = 14): Promise<CircadianRhythm> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/circadian/${childId}`, {
|
|
params: { days },
|
|
});
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get anomaly detection
|
|
getAnomalies: async (childId: string, days: number = 30): Promise<AnomalyDetection> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/anomalies/${childId}`, {
|
|
params: { days },
|
|
});
|
|
const data = response.data.data;
|
|
|
|
// Convert timestamps
|
|
return {
|
|
...data,
|
|
anomalies: data.anomalies.map((a: any) => ({
|
|
...a,
|
|
timestamp: new Date(a.timestamp),
|
|
})),
|
|
};
|
|
},
|
|
|
|
// Get activity clusters
|
|
getClusters: async (
|
|
childId: string,
|
|
activityType: string,
|
|
days: number = 30,
|
|
): Promise<PatternCluster[]> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/clusters/${childId}`, {
|
|
params: { activityType, days },
|
|
});
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get correlation analysis
|
|
getCorrelations: async (childId: string, days: number = 14): Promise<CorrelationAnalysis> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/correlations/${childId}`, {
|
|
params: { days },
|
|
});
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get trend analysis
|
|
getTrends: async (childId: string, activityType: string): Promise<TrendAnalysis> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/trends/${childId}`, {
|
|
params: { activityType },
|
|
});
|
|
const data = response.data.data;
|
|
|
|
// Convert dates in predictions
|
|
return {
|
|
...data,
|
|
prediction: {
|
|
...data.prediction,
|
|
next7Days: data.prediction.next7Days.map((p: any) => ({
|
|
...p,
|
|
date: new Date(p.date),
|
|
})),
|
|
},
|
|
};
|
|
},
|
|
|
|
// Get growth percentiles
|
|
calculateGrowthPercentiles: async (
|
|
childId: string,
|
|
measurement: {
|
|
date: Date;
|
|
weight?: number;
|
|
height?: number;
|
|
headCircumference?: number;
|
|
},
|
|
): Promise<GrowthPercentile> => {
|
|
const response = await apiClient.post(
|
|
`/api/v1/analytics/growth/percentiles/${childId}`,
|
|
{
|
|
...measurement,
|
|
date: measurement.date.toISOString(),
|
|
},
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get growth analysis
|
|
getGrowthAnalysis: async (childId: string): Promise<GrowthAnalysis> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/growth/analysis/${childId}`);
|
|
const data = response.data.data;
|
|
|
|
// Convert dates in measurements
|
|
return {
|
|
...data,
|
|
growthCurve: {
|
|
...data.growthCurve,
|
|
measurements: data.growthCurve.measurements.map((m: any) => ({
|
|
...m,
|
|
date: new Date(m.date),
|
|
})),
|
|
},
|
|
};
|
|
},
|
|
|
|
// Get comprehensive analytics dashboard
|
|
getAdvancedDashboard: async (childId: string): Promise<AdvancedAnalyticsDashboard> => {
|
|
const response = await apiClient.get(`/api/v1/analytics/advanced/dashboard/${childId}`);
|
|
const data = response.data.data;
|
|
|
|
// Process all date conversions
|
|
return {
|
|
...data,
|
|
anomalies: {
|
|
...data.anomalies,
|
|
anomalies: data.anomalies.anomalies.map((a: any) => ({
|
|
...a,
|
|
timestamp: new Date(a.timestamp),
|
|
})),
|
|
},
|
|
growthAnalysis: {
|
|
...data.growthAnalysis,
|
|
growthCurve: {
|
|
...data.growthAnalysis.growthCurve,
|
|
measurements: data.growthAnalysis.growthCurve.measurements.map((m: any) => ({
|
|
...m,
|
|
date: new Date(m.date),
|
|
})),
|
|
},
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
export enum ComparisonMetric {
|
|
SLEEP_PATTERNS = 'sleep-patterns',
|
|
FEEDING_FREQUENCY = 'feeding-frequency',
|
|
GROWTH_CURVES = 'growth-curves',
|
|
DIAPER_CHANGES = 'diaper-changes',
|
|
ACTIVITIES = 'activities',
|
|
}
|