"use client"; import { useEffect, useState } from "react"; type NutritionTotals = { calories: number; protein: number; carbs: number; fat: number; }; type NutritionGoals = { caloriesKcal: number | null; proteinG: number | null; carbsG: number | null; fatG: number | null; } | null; type NutritionCoverage = { calories: number; protein: number; carbs: number; fat: number; }; type NutritionResponse = { totals: NutritionTotals; goals: NutritionGoals; coverage: NutritionCoverage; }; interface WeeklyNutritionBarProps { weekStart: string; } type BarItem = { label: string; value: number; goal: number | null; unit: string; percentage: number; colorClass: string; }; export function WeeklyNutritionBar({ weekStart }: WeeklyNutritionBarProps) { const [data, setData] = useState(null); useEffect(() => { fetch(`/api/v1/meal-plans/${weekStart}/nutrition`) .then((res) => (res.ok ? res.json() : null)) .then((json) => setData(json)) .catch(() => setData(null)); }, [weekStart]); if (!data || !data.goals) return null; const { totals, goals, coverage } = data; const bars: BarItem[] = [ { label: "Calories", value: totals.calories, goal: goals.caloriesKcal, unit: "kcal", percentage: coverage.calories, colorClass: "bg-orange-500", }, { label: "Protein", value: totals.protein, goal: goals.proteinG, unit: "g", percentage: coverage.protein, colorClass: "bg-blue-500", }, { label: "Carbs", value: totals.carbs, goal: goals.carbsG, unit: "g", percentage: coverage.carbs, colorClass: "bg-green-500", }, { label: "Fat", value: totals.fat, goal: goals.fatG, unit: "g", percentage: coverage.fat, colorClass: "bg-yellow-500", }, ]; return (
{bars.map((bar) => { if (bar.goal == null) return null; const width = Math.min(bar.percentage, 100); return (
{bar.label} {bar.value} / {bar.goal} {bar.unit}
); })}
); }