fix(calendar): keep declaration-entry months fixed while editing

Declaring a date at the edge of the planning period widened the
projection and inserted a disabled month above the grid. Declaration
entry now lists only the planning period's months, while selections
keep the connected-period widening.

Refs #276

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nessarandClaude Opus 5.5 committed 2026-10-17 11:29:31 +02:00
1 parent feb651148e
commit a472347a5e
3 files changed
+33 -5

No files matched your search

@@ -272,11 +272,10 @@ export class CalendarYear {
const horizon = this.calendarHorizon();
if (!horizon) return undefined;
if (this.declarationEntry())
return this.calendarService.project({
placements: [],
horizon,
declaredDays: this.userInput.declaredDaysSignal(),
});
return this.calendarService.project(
{ placements: [], horizon, declaredDays: this.userInput.declaredDaysSignal() },
{ fixedMonths: true },
);
const plan = this.displayedPlan();
return this.calendarService.project(
plan ? { ...plan, horizon: plan.horizon ?? horizon } : { placements: [], horizon },
+23
View File
@@ -216,6 +216,29 @@ describe('CalendarService', () => {
]);
});
it('keeps fixed months when an edge declaration widens the projection', () => {
const plan = {
placements: [],
horizon: { start: '2024-07-01', end: '2025-01-04' },
declaredDays: [{ date: '2024-07-01', type: 'cp' as const }],
};
const months = (projection: ReturnType<typeof service.project>) =>
projection.months.map(({ monthIndex, year }) => `${year}-${monthIndex}`);
expect(months(service.project(plan))[0]).toBe('2024-5');
const fixed = service.project(plan, { fixedMonths: true });
expect(months(fixed)).toEqual([
'2024-6',
'2024-7',
'2024-8',
'2024-9',
'2024-10',
'2024-11',
'2025-0',
]);
expect(fixed.selections.dayTypes(day('2024-06-30'))).toContain(DayType.WEEKEND);
expect(fixed.selections.isStart(day('2024-07-01'))).toBe(false);
});
it('includes the final partial month of a half-open one-year horizon', () => {
const { selections } = project({ start: '2024-01-15', end: '2025-01-15' });
expect(selections.dayTypes(day('2025-01-04'))).toContain(DayType.WEEKEND);
+6
View File
@@ -72,10 +72,14 @@ export class CalendarService {
return { start, end: addPlanningYears(start, 1) };
}
/** `fixedMonths` lists only the plan horizon's months, so editing declarations never adds a month. */
project(
plan: CalendarPlan & { horizon: PlanningStateSnapshot['horizon'] },
{ fixedMonths = false } = {},
): CalendarProjection {
const horizon = calendarProjectionHorizon(plan)!;
const firstMonth = plan.horizon.start.slice(0, 7);
const lastMonth = addPlanningDays(plan.horizon.end, -1).slice(0, 7);
const first = new Date(`${horizon.start}T00:00:00`);
const last = new Date(`${horizon.end}T00:00:00`);
last.setDate(last.getDate() - 1);
@@ -92,6 +96,8 @@ export class CalendarService {
const cursor = new Date(first);
cursor.setDate(1);
while (cursor <= last) {
const month = `${cursor.getFullYear()}-${String(cursor.getMonth() + 1).padStart(2, '0')}`;
if (!fixedMonths || (month >= firstMonth && month <= lastMonth))
months.push({ monthIndex: cursor.getMonth(), year: cursor.getFullYear() });
for (const week of CalendarService.weeksInMonth(
cursor.getMonth(),