feat: Add advanced analytics UI components in frontend
- 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.
This commit is contained in:
@@ -112,6 +112,177 @@ export interface MonthlyReport {
|
||||
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> => {
|
||||
@@ -221,6 +392,139 @@ export const analyticsApi = {
|
||||
});
|
||||
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 {
|
||||
|
||||
6
maternal-web/lib/utils.ts
Normal file
6
maternal-web/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
Reference in New Issue
Block a user