Files
familysync/.planning/phases/06-ux-polish/06-01-SUMMARY.md
T

91 lines
3.9 KiB
Markdown

---
phase: 06-ux-polish
plan: "01"
subsystem: pwa/lib
tags: [tdd, date-math, event-form, d-04]
dependency_graph:
requires: []
provides:
- computeNewTimedEnd (apps/pwa/src/lib/eventDateTime.ts)
- computeNewAllDayEnd (apps/pwa/src/lib/eventDateTime.ts)
affects:
- Plan 06-06 (EventForm wires these helpers into onChange handlers)
tech_stack:
added: []
patterns:
- Local Date accessors (WR-05): getFullYear/getMonth/getDate/getHours/getMinutes — never toISOString().slice
- TDD RED→GREEN with Vitest in apps/pwa
key_files:
created: []
modified:
- apps/pwa/src/lib/eventDateTime.ts
- apps/pwa/src/lib/eventDateTime.test.ts
decisions:
- WR-05 enforced: all new date formatting uses local accessors; toISOString().slice banned for date strings
- Private helpers (localDateISO, localTimeHHMM, dateDiffDays, addDaysISO) added to eventDateTime.ts to support the two exports
metrics:
duration_minutes: 2
completed_date: "2026-06-10"
tasks_completed: 2
files_changed: 2
---
# Phase 06 Plan 01: End-Tracking Duration Math (D-04) Summary
**One-liner:** Pure duration-preservation helpers (`computeNewTimedEnd` + `computeNewAllDayEnd`) with 1h/same-day floor rules, TDD RED→GREEN in eventDateTime.ts.
## Tasks Completed
| Task | Name | Commit | Files |
|------|------|--------|-------|
| 1 (RED) | Failing tests for computeNewTimedEnd / computeNewAllDayEnd | `16cdbf3` | eventDateTime.test.ts |
| 2 (GREEN) | Implement the two end-tracking helpers | `605f543` | eventDateTime.ts |
## What Was Built
Two exported pure functions added to `apps/pwa/src/lib/eventDateTime.ts`:
- **`computeNewTimedEnd(newStartDate, newStartTime, oldStartDate, oldStartTime, oldEndDate, oldEndTime)`** — preserves a timed event's duration when the start moves. Returns `{ endDate: 'YYYY-MM-DD', endTime: 'HH:MM' }`. If the old end was already behind the old start (stale state), floors to newStart + 1 hour.
- **`computeNewAllDayEnd(newStartDate, oldStartDate, oldEndDate)`** — preserves an all-day event's inclusive day-span when the start moves. Returns `'YYYY-MM-DD'`. If the old span was negative (stale state), floors to 0 days (same day as newStart).
Four private helpers added to the same file: `localDateISO`, `localTimeHHMM`, `dateDiffDays`, `addDaysISO`. All use local Date accessors (WR-05 compliance).
## Test Coverage
Six new unit tests in `apps/pwa/src/lib/eventDateTime.test.ts`:
| Test | Behavior |
|------|----------|
| preserves a 1-hour timed delta | old 09:00→10:00; new start 11:00 → new end 12:00 |
| preserves a multi-day timed delta (26h) | old 08:00→+26h; new start same offset → correct |
| floors to 1h when old end was behind start | stale end → snaps to newStart+1h |
| preserves a 0-day span (single day all-day) | oldStart=oldEnd → newEnd=newStart |
| preserves a 3-day span | newEnd = newStart + 3 days |
| floors to same day when old end behind start | negative span → 0 → same day |
Full suite: **166/166 tests pass**. Pre-existing `serializeEventDateTime` / `localWallClockToUtcIso` tests unaffected.
## TDD Gate Compliance
- RED commit (`test(06-01): ...`): `16cdbf3` — 6 tests failing with `TypeError: computeNewTimedEnd is not a function`
- GREEN commit (`feat(06-01): ...`): `605f543` — all 166 tests pass
- RED→GREEN order confirmed via `git log`
## Deviations from Plan
None — plan executed exactly as written.
## Threat Flags
None. Pure client-side date arithmetic on already-trusted local form state. No network boundary, no new attack surface. T-06-01 accepted per threat model.
## Self-Check: PASSED
- `apps/pwa/src/lib/eventDateTime.ts` — FOUND (modified)
- `apps/pwa/src/lib/eventDateTime.test.ts` — FOUND (modified)
- Commit `16cdbf3` — FOUND (RED: test(06-01))
- Commit `605f543` — FOUND (GREEN: feat(06-01))
- `computeNewTimedEnd` export — FOUND in eventDateTime.ts
- `computeNewAllDayEnd` export — FOUND in eventDateTime.ts
- No `toISOString().slice` in helper code — CONFIRMED