import type { DateTime } from "luxon"; /** * The Monday of the week containing `date` (UTC midnight, same time-of-day * handling as `date-only.ts`). Luxon's `startOf("week")` is Monday-first by * default (ISO 8601 week numbering) regardless of locale, which already * matches the French week this app uses — no locale option needed. */ export function getWeekStart(date: DateTime): DateTime { return date.startOf("week"); } /** Shifts `date` by `n` weeks (negative to go back) — `date` need not already be a week start. */ export function addWeeks(date: DateTime, n: number): DateTime { return date.plus({ weeks: n }); } /** * Builds a fixed 6×7 (weeks × days, Monday-first) calendar grid covering * `month`, the same shape every month-picker UI in this app should use — * always 6 rows regardless of how many weeks the month actually spans, so * the grid never resizes/reflows switching between months. Leading/trailing * days from the adjacent month are included (a caller distinguishes them * with `day.hasSame(month, "month")`), not omitted. */ export function buildCalendarMonth(month: DateTime): DateTime[][] { const gridStart = getWeekStart(month.startOf("month")); const weeks: DateTime[][] = []; let cursor = gridStart; for (let week = 0; week < 6; week++) { const days: DateTime[] = []; for (let day = 0; day < 7; day++) { days.push(cursor); cursor = cursor.plus({ days: 1 }); } weeks.push(days); } return weeks; }