fix: weekly meal-plan nutrition compared a week's total against a daily goal
userNutritionGoals are daily targets (the nutrition diary already compares a single day's totals against them directly) — but the weekly meal-plan route summed an entire week's entries and compared that raw total straight against the same daily number, so coverage read roughly 7x too high. Now computes a daily average (across days that actually have planned meals) and compares that against the goal instead, adds a per-day breakdown (byDay) for a future day-view, and tracks unknownCount for entries whose recipe has no nutrition data yet, matching the diary route. Also fixed a real bug this surfaced: meal-plan/page.tsx and print/meal-plan parsed the ?week= date via new Date(dateStr) (UTC midnight) then read .getDay() (local time) — in positive-UTC-offset timezones this resolves to the wrong Monday, and the reverse (Date -> string via toISOString()) has the same mismatch in the other direction. Both now do local y/m/d math throughout. Verified locally: correct daily-average math end to end (recipe entry + batch-dish entry, which already attributed nutrition correctly via its required parent recipeId — no separate fix needed there), and confirmed the meal-plan page now resolves the right week and renders real coverage bars against actual planned entries.
This commit is contained in:
@@ -8,14 +8,29 @@ const DAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] as const;
|
||||
const MEAL_ORDER = ["breakfast", "lunch", "dinner", "snack"] as const;
|
||||
|
||||
function getMonday(dateStr?: string): Date {
|
||||
const d = dateStr ? new Date(dateStr) : new Date();
|
||||
const day = d.getDay();
|
||||
const diff = day === 0 ? -6 : 1 - day;
|
||||
// Parse y/m/d directly into local time — new Date("YYYY-MM-DD") parses as
|
||||
// UTC midnight, which getDay() (local time) can read as the wrong weekday
|
||||
// depending on the server's timezone offset.
|
||||
const d = dateStr
|
||||
? (() => {
|
||||
const [y, m, day] = dateStr.split("-").map(Number);
|
||||
return new Date(y!, m! - 1, day!);
|
||||
})()
|
||||
: new Date();
|
||||
const dow = d.getDay();
|
||||
const diff = dow === 0 ? -6 : 1 - dow;
|
||||
d.setDate(d.getDate() + diff);
|
||||
d.setHours(0, 0, 0, 0);
|
||||
return d;
|
||||
}
|
||||
|
||||
function toDateStr(d: Date): string {
|
||||
const y = d.getFullYear();
|
||||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
return `${y}-${m}-${day}`;
|
||||
}
|
||||
|
||||
export default async function MealPlanPrintPage({
|
||||
searchParams,
|
||||
}: {
|
||||
@@ -28,7 +43,7 @@ export default async function MealPlanPrintPage({
|
||||
const m = getMessages((session.user as { locale?: string }).locale);
|
||||
|
||||
const monday = getMonday(week);
|
||||
const weekStart = monday.toISOString().slice(0, 10);
|
||||
const weekStart = toDateStr(monday);
|
||||
const sunday = new Date(monday);
|
||||
sunday.setDate(sunday.getDate() + 6);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user