Schedule tab: boundary months render with only their in-horizon weeks — pad split months with unschedulable placeholders (epic #781) #785

Open
opened 2026-07-22 03:47:42 +00:00 by spikerj · 1 comment
Owner

profile?tab=schedule: the 52-week grid starts at the current week and ends at the horizon, so the FIRST month group (current July) shows only its remaining ~2 weeks and the LAST group (July 2027) only its first ~2 — a month section rendering 2 of its 4-5 week slots throws off the whole grid rhythm (spikerj report). Fix: pad both boundary months with placeholder week tiles rendered as UNSCHEDULABLE (past weeks / beyond planning horizon) — dimmed, non-interactive, tooltip explaining why — so every month section shows its full week set.

profile?tab=schedule: the 52-week grid starts at the current week and ends at the horizon, so the FIRST month group (current July) shows only its remaining ~2 weeks and the LAST group (July 2027) only its first ~2 — a month section rendering 2 of its 4-5 week slots throws off the whole grid rhythm (spikerj report). Fix: pad both boundary months with placeholder week tiles rendered as UNSCHEDULABLE (past weeks / beyond planning horizon) — dimmed, non-interactive, tooltip explaining why — so every month section shows its full week set.
Author
Owner

Audited against origin/masterthe model half landed; the template was never wired. Staying open.

Landed (angular PR #519, f376fa11):

  • schedule-tab.component.ts:137-170padBoundaryMonths, emitting placeholders with schedulable: false and unschedulableReason: "past" | "beyondHorizon"; applied at :101,106.
  • :188cycleWeek guards on !week.schedulable.
  • schedule-tab.component.scss:182-188.week-cell.unschedulable (dimmed, dashed border, hatched, line-through).
  • i18n in both files with matching keys: profile.schedule.unschedulablePast / unschedulableBeyond.

Never wired. schedule-tab.component.html:69-77 binds only [class.free] [class.limited] [class.busy] [class.overridden], sets [matTooltip]="week.overridden ? … : ''", and attaches an unconditional (click)="cycleWeek(week)". The proof that the SCSS rule and both i18n keys are orphaned: git grep -n "unschedulablePast\|unschedulableBeyond\|\.unschedulable" origin/master outside assets/i18n/ returns only the .scss definition itself and the .ts/.spec.ts model references — zero hits in any template.

Net effect today: the boundary months do get padded, so the grid rhythm bug is fixed, and clicking a placeholder is a harmless no-op thanks to the :188 guard. But placeholders render as ordinary interactive tiles — the ticket's "dimmed, non-interactive, with a tooltip explaining why" is unmet.

Why this shipped green — worth recording, because it's a repeatable trap: the 4 new specs assert on the component's GridWeek model output (schedule-tab.component.spec.ts:52,60), not on rendered DOM. A model-level test cannot catch a template that never consumes the model.

Remaining: add [class.unschedulable]="!week.schedulable", drive the tooltip off unschedulableReason, and make the week button non-interactive ([disabled] or removing the handler) rather than relying on the silent guard.

Audited against `origin/master` — **the model half landed; the template was never wired.** Staying open. **Landed** (angular PR #519, `f376fa11`): - `schedule-tab.component.ts:137-170` — `padBoundaryMonths`, emitting placeholders with `schedulable: false` and `unschedulableReason: "past" | "beyondHorizon"`; applied at `:101,106`. - `:188` — `cycleWeek` guards on `!week.schedulable`. - `schedule-tab.component.scss:182-188` — `.week-cell.unschedulable` (dimmed, dashed border, hatched, line-through). - i18n in **both** files with matching keys: `profile.schedule.unschedulablePast` / `unschedulableBeyond`. **Never wired.** `schedule-tab.component.html:69-77` binds only `[class.free] [class.limited] [class.busy] [class.overridden]`, sets `[matTooltip]="week.overridden ? … : ''"`, and attaches an unconditional `(click)="cycleWeek(week)"`. The proof that the SCSS rule and both i18n keys are orphaned: `git grep -n "unschedulablePast\|unschedulableBeyond\|\.unschedulable" origin/master` outside `assets/i18n/` returns **only** the `.scss` definition itself and the `.ts`/`.spec.ts` model references — **zero hits in any template**. **Net effect today:** the boundary months *do* get padded, so the grid rhythm bug is fixed, and clicking a placeholder is a harmless no-op thanks to the `:188` guard. But placeholders render as ordinary interactive tiles — the ticket's "dimmed, non-interactive, with a tooltip explaining why" is unmet. **Why this shipped green** — worth recording, because it's a repeatable trap: the 4 new specs assert on the component's `GridWeek` model output (`schedule-tab.component.spec.ts:52,60`), not on rendered DOM. A model-level test cannot catch a template that never consumes the model. **Remaining:** add `[class.unschedulable]="!week.schedulable"`, drive the tooltip off `unschedulableReason`, and make the week button non-interactive (`[disabled]` or removing the handler) rather than relying on the silent guard.
Sign in to join this conversation.