import { useT } from "@agent-native/core/client/i18n"; import type { DailyCalories } from "@shared/types"; import { startOfWeek, endOfWeek, format, parseISO, isToday, isBefore, startOfDay, } from "date-fns"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceLine, Cell, } from "recharts"; import { Skeleton } from "@/components/ui/skeleton"; interface WeeklyData { weekLabel: string; weekStart: string; netCalories: number; totalCalories: number; burnedCalories: number; daysTracked: number; weeklyGoal: number; projectedCalories: number; isCurrentWeek: boolean; completedDays: number; } interface WeeklyCaloriesChartProps { history: DailyCalories[] | undefined; isLoading: boolean; dailyGoal?: number; } function aggregateWeekly( history: DailyCalories[], dailyGoal: number, ): WeeklyData[] { const now = new Date(); const currentWeekStart = format( startOfWeek(now, { weekStartsOn: 1 }), "yyyy-MM-dd", ); const todayStart = startOfDay(now); const weekMap = new Map< string, { netCalories: number; totalCalories: number; burnedCalories: number; daysTracked: number; completedDayCalories: number; completedDays: number; weekStart: Date; weekEnd: Date; } >(); for (const day of history) { const date = parseISO(day.date); const ws = startOfWeek(date, { weekStartsOn: 1 }); const we = endOfWeek(date, { weekStartsOn: 1 }); const key = format(ws, "yyyy-MM-dd"); const existing = weekMap.get(key) || { netCalories: 0, totalCalories: 0, burnedCalories: 0, daysTracked: 0, completedDayCalories: 0, completedDays: 0, weekStart: ws, weekEnd: we, }; existing.netCalories += day.netCalories; existing.totalCalories += day.totalCalories; existing.burnedCalories += day.burnedCalories; existing.daysTracked += 1; const isCompletedDay = isBefore(date, todayStart) && !isToday(date); if (isCompletedDay) { existing.completedDayCalories += day.netCalories; existing.completedDays += 1; } weekMap.set(key, existing); } return Array.from(weekMap.entries()) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, week]) => { const isCurrentWeek = key === currentWeekStart; let projectedCalories = 0; if (isCurrentWeek && week.completedDays > 0) { const avgPerDay = week.completedDayCalories / week.completedDays; projectedCalories = Math.round(avgPerDay * (7 - week.daysTracked)); } return { weekLabel: `${format(week.weekStart, "MMM d")} - ${format(week.weekEnd, "MMM d")}`, weekStart: key, netCalories: week.netCalories, totalCalories: week.totalCalories, burnedCalories: week.burnedCalories, daysTracked: week.daysTracked, weeklyGoal: dailyGoal * 7, projectedCalories, isCurrentWeek, completedDays: week.completedDays, }; }); } function CustomTooltip({ active, payload, t }: any) { if (!active || !payload?.[0]) return null; const data = payload[0].payload as WeeklyData; const projected = data.netCalories + data.projectedCalories; const diff = data.netCalories - data.weeklyGoal; const isOver = diff > 0; return (
{data.weekLabel}
{t("weekly.eaten", { calories: data.totalCalories.toLocaleString() })}
{t("weekly.burned", { calories: data.burnedCalories.toLocaleString(), })}
{t("weekly.goal", { calories: data.weeklyGoal.toLocaleString() })}
{t("weekly.vsGoal", { sign: isOver ? "+" : "", diff: diff.toLocaleString(), })}
{t("weekly.daysTracked", { count: data.daysTracked })} {data.isCurrentWeek && ` ยท ${t("weekly.completed", { count: data.completedDays })}`}
{t("weekly.noData")}
{t("weekly.noDataDescription")}
{s.label}