diff --git a/apps/pwa/src/lib/eventDateTime.ts b/apps/pwa/src/lib/eventDateTime.ts index 5122299..df51af0 100644 --- a/apps/pwa/src/lib/eventDateTime.ts +++ b/apps/pwa/src/lib/eventDateTime.ts @@ -68,8 +68,12 @@ function pad2(n: number): string { return n < 10 ? `0${n}` : `${n}` } -/** Format a Date as 'YYYY-MM-DD' using LOCAL calendar accessors. */ -function localDateISO(d: Date): string { +/** + * Format a Date as 'YYYY-MM-DD' using LOCAL calendar accessors. + * WR-04: exported as the single source for local-date formatting so calendarStore + * (initialCalendarRange/todayIso) can drop its banned toISOString().slice(0,10). + */ +export function localDateISO(d: Date): string { return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}` } diff --git a/apps/pwa/src/store/calendarStore.ts b/apps/pwa/src/store/calendarStore.ts index 34fa668..6c73891 100644 --- a/apps/pwa/src/store/calendarStore.ts +++ b/apps/pwa/src/store/calendarStore.ts @@ -24,6 +24,7 @@ */ import { create } from 'zustand' +import { localDateISO } from '../lib/eventDateTime.js' // ── Types ────────────────────────────────────────────────────────────────── @@ -126,15 +127,19 @@ function initialCalendarRange(): { start: string; end: string } { start.setDate(start.getDate() - 7) const end = new Date(today.getFullYear(), today.getMonth() + 1, 0) end.setDate(end.getDate() + 7) + // WR-04: localDateISO uses local calendar accessors — NEVER toISOString().slice(0,10), + // which returns the UTC date and (for the project's negative-offset zones after ~20:00 + // local) seeds the window/selectedDate on the wrong day. return { - start: start.toISOString().slice(0, 10), - end: end.toISOString().slice(0, 10), + start: localDateISO(start), + end: localDateISO(end), } } /** Today as an ISO date string (YYYY-MM-DD). Exported for use in EventForm (IN-03). */ export function todayIso(): string { - return new Date().toISOString().slice(0, 10) + // WR-04: local-date accessor, not the banned UTC slice. + return localDateISO(new Date()) } // ── Store ──────────────────────────────────────────────────────────────────