import { useActionQuery } from "@agent-native/core/client/hooks"; import { useT } from "@agent-native/core/client/i18n"; import { IconTrendingUp, IconActivity, IconChartBar, } from "@tabler/icons-react"; import { subDays } from "date-fns"; import type { CSSProperties } from "react"; import { useState, useEffect } from "react"; import { Link } from "react-router"; import { LineChart, Line, XAxis, YAxis, Tooltip as ChartTooltip, ResponsiveContainer, AreaChart, Area, } from "recharts"; import { QueryErrorState } from "@/components/QueryErrorState"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { cn, formatLocalDate } from "@/lib/utils"; function readActiveChart() { if (typeof window === "undefined") return "weight"; try { return window.localStorage.getItem("hero_active_chart") || "weight"; } catch { return "weight"; } } function writeActiveChart(activeChart: string) { if (typeof window === "undefined") return; try { window.localStorage.setItem("hero_active_chart", activeChart); } catch { // Ignore unavailable storage; the in-memory tab state still works. } } interface DailyProgressProps { totalCalories: number; totalBurnedCalories: number; goalCalories: number; protein: number; carbs: number; fat: number; } const chartTooltipContentStyle = { backgroundColor: "hsl(var(--popover))", border: "1px solid hsl(var(--border))", borderRadius: "8px", boxShadow: "0 4px 12px hsl(var(--foreground) / 0.12)", color: "hsl(var(--popover-foreground))", fontSize: "12px", } satisfies CSSProperties; export function DailyProgress({ totalCalories, totalBurnedCalories, goalCalories, protein, carbs, fat, }: DailyProgressProps) { const t = useT(); const [activeChart, setActiveChart] = useState(readActiveChart); useEffect(() => { writeActiveChart(activeChart); }, [activeChart]); const netCalories = totalCalories - totalBurnedCalories; const percentage = Math.max( 0, Math.min(100, (netCalories / goalCalories) * 100), ); const remaining = Math.max(0, goalCalories - netCalories); const isOver = netCalories > goalCalories; const endDate = formatLocalDate(new Date()); const startDate = formatLocalDate(subDays(new Date(), 30)); const weightHistoryQuery = useActionQuery( "weights-history", { startDate, endDate }, { enabled: activeChart === "weight" }, ); const { data: rawWeightHistory, isLoading: weightLoading } = weightHistoryQuery; const weightHistory = Array.isArray(rawWeightHistory) ? rawWeightHistory : []; const calorieHistoryQuery = useActionQuery( "meals-history", { startDate, endDate }, { enabled: activeChart === "activity" }, ); const { data: rawCalorieHistory, isLoading: calorieLoading } = calorieHistoryQuery; const calorieHistory = Array.isArray(rawCalorieHistory) ? rawCalorieHistory : []; const getYDomain = (data: any[], key: string) => { if (!data || data.length === 0) return [0, 100]; const values = data.map((h) => h[key]); const min = Math.min(...values); const max = Math.max(...values); const padding = (max - min) * 0.2 || 10; return [Math.floor(min - padding), Math.ceil(max + padding)]; }; return (
{t("daily.summary")}
{m.label}
{m.value}g
{t("daily.noWeightData")}
{t("daily.currentWeight", { weight: weightHistory[weightHistory.length - 1].weight, })}
)}{t("daily.noActivityData")}