"use client"; import { useEffect, useState } from "react"; import { useTranslations } from "next-intl"; import { TimeSeriesChart, type TimeSeriesPoint } from "@/components/admin/charts/time-series-chart"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; type TrendDay = { date: string; calories: number; proteinG: number; carbsG: number; fatG: number }; type TrendResponse = { range: number; days: TrendDay[]; goalCalories: number | null }; const RANGES = [7, 30, 90] as const; export function NutritionTrend() { const t = useTranslations("nutritionDiary"); const [range, setRange] = useState(30); // Tagged with the range it was fetched for, and set only from inside the // fetch's own then/catch — same pattern as nutrition-diary.tsx — so no // separate setState call is needed synchronously in the effect body. const [result, setResult] = useState< { range: number; ok: true; data: TrendResponse } | { range: number; ok: false } | null >(null); useEffect(() => { let cancelled = false; fetch(`/api/v1/users/me/nutrition-diary?range=${range}`) .then((res) => (res.ok ? res.json() : Promise.reject(new Error("request failed")))) .then((json: TrendResponse) => { if (!cancelled) setResult({ range, ok: true, data: json }); }) .catch(() => { if (!cancelled) setResult({ range, ok: false }); }); return () => { cancelled = true; }; }, [range]); const error = result !== null && result.range === range && !result.ok; const data = result !== null && result.range === range && result.ok ? result.data : null; const caloriePoints: TimeSeriesPoint[] = data?.days.map((d) => ({ date: d.date, value: d.calories })) ?? []; const avg = data && data.days.length > 0 ? { proteinG: Math.round(data.days.reduce((s, d) => s + d.proteinG, 0) / data.days.length), carbsG: Math.round(data.days.reduce((s, d) => s + d.carbsG, 0) / data.days.length), fatG: Math.round(data.days.reduce((s, d) => s + d.fatG, 0) / data.days.length), } : null; return (

{t("trendCaloriesTitle")}

{error &&

{t("loadError")}

} {!error && data && ( <> `${n} kcal`} dateFormat="day" /> {avg && (
{t("protein")} {t("trendDailyAvg", { value: `${avg.proteinG}g` })}
{t("carbs")} {t("trendDailyAvg", { value: `${avg.carbsG}g` })}
{t("fat")} {t("trendDailyAvg", { value: `${avg.fatG}g` })}
)} )}
); }