122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import { NutritionSummary } from "@fitai/shared";
|
|
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
|
import {
|
|
PieChart,
|
|
Pie,
|
|
Cell,
|
|
ResponsiveContainer,
|
|
Legend,
|
|
Tooltip,
|
|
} from "recharts";
|
|
|
|
interface NutritionSummaryCardProps {
|
|
nutrition: {
|
|
dailySummaries: NutritionSummary[];
|
|
averageDailyCalories: number;
|
|
totalDays: number;
|
|
daysMetGoal: number;
|
|
};
|
|
}
|
|
|
|
export function NutritionSummaryCard({ nutrition }: NutritionSummaryCardProps) {
|
|
const goalMetPercentage =
|
|
nutrition.totalDays > 0
|
|
? Math.round((nutrition.daysMetGoal / nutrition.totalDays) * 100)
|
|
: 0;
|
|
|
|
const chartData = [
|
|
{ name: "Days Met Goal", value: nutrition.daysMetGoal, color: "#10b981" },
|
|
{
|
|
name: "Days Over/Under",
|
|
value: nutrition.totalDays - nutrition.daysMetGoal,
|
|
color: "#f59e0b",
|
|
},
|
|
];
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Nutrition Summary</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
{/* Summary Stats */}
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-blue-600">
|
|
{nutrition.averageDailyCalories.toLocaleString()}
|
|
</div>
|
|
<div className="text-xs text-gray-600">Avg Daily Calories</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-green-600">
|
|
{nutrition.totalDays}
|
|
</div>
|
|
<div className="text-xs text-gray-600">Days Tracked</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Goal Achievement */}
|
|
<div className="text-center">
|
|
<div className="text-3xl font-bold text-purple-600">
|
|
{goalMetPercentage}%
|
|
</div>
|
|
<div className="text-xs text-gray-600">
|
|
Days Met Calorie Goal (±10%)
|
|
</div>
|
|
</div>
|
|
|
|
{/* Chart */}
|
|
{nutrition.totalDays > 0 && (
|
|
<div className="h-48">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<PieChart>
|
|
<Pie
|
|
data={chartData}
|
|
cx="50%"
|
|
cy="50%"
|
|
innerRadius={40}
|
|
outerRadius={70}
|
|
paddingAngle={5}
|
|
dataKey="value"
|
|
>
|
|
{chartData.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip />
|
|
<Legend />
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)}
|
|
|
|
{/* Recent Days */}
|
|
{nutrition.dailySummaries.length > 0 && (
|
|
<div className="space-y-2">
|
|
<h4 className="text-sm font-semibold">Recent Days</h4>
|
|
<div className="max-h-32 overflow-y-auto space-y-1">
|
|
{nutrition.dailySummaries
|
|
.slice(-5)
|
|
.reverse()
|
|
.map((day) => (
|
|
<div
|
|
key={day.date}
|
|
className="flex justify-between items-center text-sm"
|
|
>
|
|
<span className="text-gray-600">{day.date}</span>
|
|
<span className="font-medium">
|
|
{day.totalCalories.toLocaleString()} /{" "}
|
|
{day.calorieGoal.toLocaleString()} cal
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|