style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
@@ -3,7 +3,7 @@ phase: 02-calendar-display
plan: 05
type: execute
wave: 4
depends_on: ["02-04"]
depends_on: ['02-04']
files_modified:
- apps/pwa/src/components/EventDetailPopover.tsx
- apps/pwa/src/components/ColorLegend.tsx
@@ -20,30 +20,30 @@ user_setup: []
must_haves:
truths:
- "Tapping any event opens a read-only detail popover (title, date/time, location, description, calendar name + owner color) built for Phase 3 reuse as the edit surface"
- 'Tapping any event opens a read-only detail popover (title, date/time, location, description, calendar name + owner color) built for Phase 3 reuse as the edit surface'
- "A color legend (member → color, plus 'Family' rose row) is always visible so ownership is decodable"
- "Initial load shows a shimmer skeleton; a successful fetch with zero events shows the empty state; a failed fetch shows the error state with a working Retry"
- "All chrome (AppNav, ViewToolbar, legend) is token-styled with 44px minimum touch targets and is keyboard/focus accessible"
- "The popover never renders event fields via dangerouslySetInnerHTML (XSS guard) and traps focus with Escape-to-close"
- 'Initial load shows a shimmer skeleton; a successful fetch with zero events shows the empty state; a failed fetch shows the error state with a working Retry'
- 'All chrome (AppNav, ViewToolbar, legend) is token-styled with 44px minimum touch targets and is keyboard/focus accessible'
- 'The popover never renders event fields via dangerouslySetInnerHTML (XSS guard) and traps focus with Escape-to-close'
artifacts:
- path: "apps/pwa/src/components/EventDetailPopover.tsx"
provides: "read-only event detail popover; Phase-3-reusable edit surface; focus trap + XSS-safe"
exports: ["EventDetailPopover"]
- path: "apps/pwa/src/components/ColorLegend.tsx"
provides: "always-visible member→color legend with Family row"
exports: ["ColorLegend"]
- path: "apps/pwa/src/components/SkeletonCalendar.tsx"
provides: "shimmer loading skeleton (month + agenda variants)"
exports: ["SkeletonCalendar"]
- path: 'apps/pwa/src/components/EventDetailPopover.tsx'
provides: 'read-only event detail popover; Phase-3-reusable edit surface; focus trap + XSS-safe'
exports: ['EventDetailPopover']
- path: 'apps/pwa/src/components/ColorLegend.tsx'
provides: 'always-visible member→color legend with Family row'
exports: ['ColorLegend']
- path: 'apps/pwa/src/components/SkeletonCalendar.tsx'
provides: 'shimmer loading skeleton (month + agenda variants)'
exports: ['SkeletonCalendar']
key_links:
- from: "apps/pwa/src/components/CalendarShell.tsx"
to: "apps/pwa/src/components/EventDetailPopover.tsx"
via: "customComponents.eventModal + openEventId from Zustand"
pattern: "EventDetailPopover"
- from: "apps/pwa/src/components/CalendarShell.tsx"
to: "SkeletonCalendar | EmptyState | error state"
via: "TanStack Query isLoading/empty/isError branches"
pattern: "SkeletonCalendar"
- from: 'apps/pwa/src/components/CalendarShell.tsx'
to: 'apps/pwa/src/components/EventDetailPopover.tsx'
via: 'customComponents.eventModal + openEventId from Zustand'
pattern: 'EventDetailPopover'
- from: 'apps/pwa/src/components/CalendarShell.tsx'
to: 'SkeletonCalendar | EmptyState | error state'
via: 'TanStack Query isLoading/empty/isError branches'
pattern: 'SkeletonCalendar'
---
<objective>
@@ -98,6 +98,7 @@ EventProof removed; human-verify checkpoint.
Wire into CalendarShell: pass `customComponents={{ eventModal: EventDetailPopover }}` to `<ScheduleXCalendar>`, and ensure the event-click path sets openEventId so the popover opens. Keep the eventsService/eventModal plugin wiring from Plan 04.
Write `EventDetailPopover.test.tsx` (jsdom): renders an event's fields as text, Escape triggers close, and asserts no dangerouslySetInnerHTML usage (render a title containing an HTML-looking string and assert it appears escaped as text).
</action>
<verify>
<automated>cd apps/pwa && pnpm test -- src/components/EventDetailPopover.test.tsx</automated>
@@ -134,6 +135,7 @@ EventProof removed; human-verify checkpoint.
In CalendarShell, render AppNav + ViewToolbar + ColorLegend chrome around `<ScheduleXCalendar>` (grid is the primary focal point per reviewer note). Branch on the events query: `isLoading` (initial) → SkeletonCalendar; success + `occurrences.length === 0` → EmptyState; `isError` (after retry:2) → error state replacing the grid with heading "Couldn't load events", body "Check your connection and try again.", and a "Retry" button calling `queryClient.refetchQueries({ queryKey: ['events'] })`. All token-styled.
Delete `apps/pwa/src/components/EventProof.tsx` and remove any remaining imports/references to it (Plan 04 removed it from the render path; confirm the file and its imports are gone).
</action>
<verify>
<automated>cd apps/pwa && grep -q "SkeletonCalendar" src/components/CalendarShell.tsx && grep -q "EmptyState" src/components/CalendarShell.tsx && grep -q "Couldn't load events" src/components/CalendarShell.tsx && grep -q "ColorLegend" src/components/CalendarShell.tsx && echo STATES_WIRED</automated>
@@ -174,18 +176,20 @@ EventProof removed; human-verify checkpoint.
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Boundary | Description |
| -------------------------- | ---------------------------------------------------- |
| event fields → popover DOM | title/location/description rendered into the popover |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-02e-01 | Tampering (XSS) | EventDetailPopover event fields | mitigate | Plain-text JSX children only; no dangerouslySetInnerHTML; test asserts HTML-looking title renders escaped |
| T-02e-02 | Denial of service | Retry button hammering /api/events | accept | Manual user action, retry:2 backoff already on the query; two-person self-hosted app, negligible risk |
| Threat ID | Category | Component | Disposition | Mitigation Plan |
| --------- | ----------------- | ---------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------- |
| T-02e-01 | Tampering (XSS) | EventDetailPopover event fields | mitigate | Plain-text JSX children only; no dangerouslySetInnerHTML; test asserts HTML-looking title renders escaped |
| T-02e-02 | Denial of service | Retry button hammering /api/events | accept | Manual user action, retry:2 backoff already on the query; two-person self-hosted app, negligible risk |
</threat_model>
<verification>
@@ -195,14 +199,16 @@ EventProof removed; human-verify checkpoint.
</verification>
<success_criteria>
- Color-coded events + legend decode ownership (criterion 1)
- All four views render events correctly (criterion 2)
- Recurring occurrences correct incl. DST (criterion 3)
- All-day events as full-day banners with no shift (criterion 4)
- Tap-to-expand popover + skeleton/empty/error states polished and accessible
</success_criteria>
</success_criteria>
<artifacts_produced>
## Artifacts this phase produces (Plan 05)
- `EventDetailPopover` (React component, Phase-3-reusable edit surface) — EventDetailPopover.tsx
@@ -210,7 +216,7 @@ EventProof removed; human-verify checkpoint.
- CalendarShell: chrome + loading/empty/error branches + customComponents.eventModal wiring
- EventProof.tsx DELETED (Phase 1 proof component retired)
- EventDetailPopover.test.tsx
</artifacts_produced>
</artifacts_produced>
<output>
Create `.planning/phases/02-calendar-display/02-05-SUMMARY.md` when done