feat: Add enhanced analytics dashboard with advanced visualizations
- Created EnhancedInsightsDashboard with multiple chart types: - Area charts with gradients for activity trends - Radar chart for weekly activity patterns - 24-hour heatmap visualization - Bubble/scatter chart for correlations - Time of day distribution bar chart - Added toggle between basic and enhanced chart views - Implemented chart export functionality (PNG/PDF) - Fixed API endpoint URLs (circadian-rhythm, query params) - Fixed component library conflicts (shadcn/ui → MUI) - Added comprehensive null safety for timestamp handling - Added alert type translations in all 5 languages - Installed html2canvas and jspdf for export features - Applied consistent minimum width styling to all charts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,7 @@ export default function AdvancedAnalyticsPage() {
|
||||
const [selectedChildId, setSelectedChildId] = useState<string>('');
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string>('');
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
// Analytics data states
|
||||
const [circadianData, setCircadianData] = useState<CircadianRhythm | null>(null);
|
||||
@@ -259,19 +260,16 @@ export default function AdvancedAnalyticsPage() {
|
||||
Select Child:
|
||||
</label>
|
||||
<Select
|
||||
id="child-select"
|
||||
value={selectedChildId}
|
||||
onValueChange={setSelectedChildId}
|
||||
onChange={(e) => setSelectedChildId(e.target.value as string)}
|
||||
sx={{ minWidth: 200 }}
|
||||
>
|
||||
<SelectTrigger className="w-[200px]">
|
||||
<SelectValue placeholder="Select a child" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{children.map((child) => (
|
||||
<SelectItem key={child.id} value={child.id}>
|
||||
{child.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
{children.map((child) => (
|
||||
<MenuItem key={child.id} value={child.id}>
|
||||
{child.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -285,79 +283,91 @@ export default function AdvancedAnalyticsPage() {
|
||||
)}
|
||||
|
||||
{/* Analytics Tabs */}
|
||||
<Tabs defaultValue="circadian" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-5">
|
||||
<TabsTrigger value="circadian">
|
||||
<Brain className="h-4 w-4 mr-2" />
|
||||
Sleep Rhythm
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="anomalies">
|
||||
<Activity className="h-4 w-4 mr-2" />
|
||||
Anomalies
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="growth">
|
||||
<Baby className="h-4 w-4 mr-2" />
|
||||
Growth
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="correlations">
|
||||
<Link className="h-4 w-4 mr-2" />
|
||||
Correlations
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="trends">
|
||||
<TrendingUp className="h-4 w-4 mr-2" />
|
||||
Trends
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="circadian" className="space-y-4">
|
||||
<CircadianRhythmCard
|
||||
data={circadianData}
|
||||
loading={circadianLoading}
|
||||
error={circadianError}
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onChange={(e, newValue) => setActiveTab(newValue)}
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab
|
||||
icon={<Brain style={{ width: 16, height: 16 }} />}
|
||||
iconPosition="start"
|
||||
label="Sleep Rhythm"
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="anomalies" className="space-y-4">
|
||||
<AnomalyAlertsPanel
|
||||
data={anomalyData}
|
||||
loading={anomalyLoading}
|
||||
error={anomalyError}
|
||||
<Tab
|
||||
icon={<Activity style={{ width: 16, height: 16 }} />}
|
||||
iconPosition="start"
|
||||
label="Anomalies"
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="growth" className="space-y-4">
|
||||
<GrowthPercentileChart
|
||||
data={growthData}
|
||||
loading={growthLoading}
|
||||
error={growthError}
|
||||
<Tab
|
||||
icon={<Baby style={{ width: 16, height: 16 }} />}
|
||||
iconPosition="start"
|
||||
label="Growth"
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="correlations" className="space-y-4">
|
||||
<CorrelationInsights
|
||||
data={correlationData}
|
||||
loading={correlationLoading}
|
||||
error={correlationError}
|
||||
<Tab
|
||||
icon={<Link style={{ width: 16, height: 16 }} />}
|
||||
iconPosition="start"
|
||||
label="Correlations"
|
||||
/>
|
||||
</TabsContent>
|
||||
<Tab
|
||||
icon={<TrendingUp style={{ width: 16, height: 16 }} />}
|
||||
iconPosition="start"
|
||||
label="Trends"
|
||||
/>
|
||||
</Tabs>
|
||||
|
||||
<TabsContent value="trends" className="space-y-4">
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<TrendAnalysisChart
|
||||
data={sleepTrendData}
|
||||
activityType="Sleep"
|
||||
loading={trendLoading}
|
||||
error={trendError}
|
||||
<Box sx={{ py: 3 }}>
|
||||
{activeTab === 0 && (
|
||||
<CircadianRhythmCard
|
||||
data={circadianData}
|
||||
loading={circadianLoading}
|
||||
error={circadianError}
|
||||
/>
|
||||
<TrendAnalysisChart
|
||||
data={feedingTrendData}
|
||||
activityType="Feeding"
|
||||
loading={trendLoading}
|
||||
error={trendError}
|
||||
)}
|
||||
|
||||
{activeTab === 1 && (
|
||||
<AnomalyAlertsPanel
|
||||
data={anomalyData}
|
||||
loading={anomalyLoading}
|
||||
error={anomalyError}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
)}
|
||||
|
||||
{activeTab === 2 && (
|
||||
<GrowthPercentileChart
|
||||
data={growthData}
|
||||
loading={growthLoading}
|
||||
error={growthError}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeTab === 3 && (
|
||||
<CorrelationInsights
|
||||
data={correlationData}
|
||||
loading={correlationLoading}
|
||||
error={correlationError}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeTab === 4 && (
|
||||
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))' }}>
|
||||
<TrendAnalysisChart
|
||||
data={sleepTrendData}
|
||||
activityType="Sleep"
|
||||
loading={trendLoading}
|
||||
error={trendError}
|
||||
/>
|
||||
<TrendAnalysisChart
|
||||
data={feedingTrendData}
|
||||
activityType="Feeding"
|
||||
loading={trendLoading}
|
||||
error={trendError}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</div>
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
|
||||
Reference in New Issue
Block a user