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:
@@ -17,16 +17,30 @@ import { getMessages, formatMessage } from "@/lib/i18n/server";
|
||||
export const metadata: Metadata = {};
|
||||
|
||||
function getMonday(dateStr?: string): Date {
|
||||
const d = dateStr ? new Date(dateStr) : new Date();
|
||||
const day = d.getDay();
|
||||
const diff = (day === 0 ? -6 : 1 - day);
|
||||
// new Date("YYYY-MM-DD") parses as UTC midnight, but getDay() below reads
|
||||
// local time — in negative UTC-offset zones that's still "yesterday",
|
||||
// shifting the resolved Monday back by a full week. Parse the y/m/d parts
|
||||
// directly into local time instead.
|
||||
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 {
|
||||
return d.toISOString().slice(0, 10);
|
||||
// Read local y/m/d, not toISOString() (which converts to UTC and can
|
||||
// shift the date by a day depending on the server's timezone offset).
|
||||
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}`;
|
||||
}
|
||||
|
||||
function addWeeks(d: Date, n: number): Date {
|
||||
|
||||
Reference in New Issue
Block a user