Spaces:
Running
Running
| "use client"; | |
| import { useState, useEffect, useCallback } from "react"; | |
| interface DashboardProfile { | |
| display_name: string | null; | |
| onboarding_completed: boolean; | |
| } | |
| interface AdHocMedication { | |
| name: string; | |
| dose: string | null; | |
| logged_at: string | null; | |
| } | |
| interface ScheduledMedication { | |
| name: string; | |
| status: "logged" | "pending"; | |
| logged_at: string | null; | |
| scheduled_window: string; | |
| } | |
| interface MedicationStats { | |
| taken: number; | |
| total: number; | |
| ad_hoc: AdHocMedication[]; | |
| scheduled: ScheduledMedication[]; | |
| } | |
| interface HeadacheDay { | |
| day: string; | |
| intensity: number; | |
| count: number; | |
| } | |
| export interface DashboardStats { | |
| profile: DashboardProfile; | |
| medication: MedicationStats; | |
| days_active_this_week: number; | |
| headaches: HeadacheDay[]; | |
| } | |
| const DEFAULT_STATS: DashboardStats = { | |
| profile: { display_name: null, onboarding_completed: false }, | |
| medication: { taken: 0, total: 0, ad_hoc: [], scheduled: [] }, | |
| days_active_this_week: 0, | |
| headaches: [], | |
| }; | |
| export function useDashboardData() { | |
| const [stats, setStats] = useState<DashboardStats>(DEFAULT_STATS); | |
| const [isLoading, setIsLoading] = useState(true); | |
| const [error, setError] = useState<string | null>(null); | |
| const fetchStats = useCallback(async () => { | |
| try { | |
| const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:7860"; | |
| const response = await fetch(`${apiUrl}/api/stream/dashboard-stats`); | |
| if (!response.ok) { | |
| throw new Error(`Failed to fetch dashboard stats: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| setStats(data); | |
| setError(null); | |
| } catch (err) { | |
| console.error("Dashboard stats error:", err); | |
| setError(err instanceof Error ? err.message : "Failed to load dashboard"); | |
| // Keep default stats on error | |
| } finally { | |
| setIsLoading(false); | |
| } | |
| }, []); | |
| useEffect(() => { | |
| // Fetch once on mount | |
| fetchStats(); | |
| // Re-fetch when backend pushes dashboard.updated via WebSocket | |
| // or when settings change (profile name, DB reset, etc.) | |
| const handleRefresh = () => { | |
| fetchStats(); | |
| }; | |
| window.addEventListener("dashboard-updated", handleRefresh); | |
| window.addEventListener("settings-updated", handleRefresh); | |
| return () => { | |
| window.removeEventListener("dashboard-updated", handleRefresh); | |
| window.removeEventListener("settings-updated", handleRefresh); | |
| }; | |
| }, [fetchStats]); | |
| return { stats, isLoading, error, refetch: fetchStats }; | |
| } | |