---
phase: 18-auto-timezone-detection-and-ability-to-change-timezone
plan: "04"
subsystem: pwa
tags: [timezone, iana, admin, react, tanstack-query, playwright, ui]
# Dependency graph
requires:
- phase: 18-02
provides: GET/PUT /api/admin/config/timezone (consumed by fetchAdminTimezone/setAdminTimezone)
provides:
- fetchAdminTimezone() — GET /api/admin/config/timezone in PWA API client
- setAdminTimezone(tz) — PUT /api/admin/config/timezone in PWA API client
- AdminTimezoneResponse interface (timezone: string, isExplicitlySet: boolean)
- Timezone section in AdminPage (/admin) — searchable IANA picker, save, detected-zone affordance
affects:
- apps/pwa/src/api/client.ts
- apps/pwa/src/routes/AdminPage.tsx
- apps/pwa/e2e/timezone-verify.spec.ts (new verification spec)
# Tech tracking
tech-stack:
added: []
patterns:
- Intl.supportedValuesOf('timeZone') guarded for runtime availability (datalist population)
- ARIA combobox role for — Playwright locator uses getByRole('combobox') not getByRole('textbox')
- useQuery + useMutation with invalidateQueries on success (same pattern as calendars section)
key-files:
created:
- apps/pwa/e2e/timezone-verify.spec.ts
modified:
- apps/pwa/src/api/client.ts
- apps/pwa/src/routes/AdminPage.tsx
key-decisions:
- "Removed AdminTimezoneResponse from AdminPage.tsx import list — ESLint no-unused-vars; type is inferred from useQuery return"
- "Input with list= attribute has ARIA combobox role in Chromium, not textbox — Playwright e2e uses getByRole('combobox')"
- "timezoneInput state is null when the user has not interacted — effectiveTimezoneInput = timezoneInput ?? storedTimezone preserves stored value as pre-fill"
- "setTimezoneInput(null) on mutation success resets local override so save button re-disables to match new stored value"
requirements-completed: [D-02, D-04]
# Metrics
duration: 15min
completed: 2026-06-15
---
# Phase 18 Plan 04: Admin Timezone UI Summary
**Searchable IANA timezone picker in /admin Settings — fetchAdminTimezone/setAdminTimezone in client.ts + Timezone section in AdminPage.tsx — verified end-to-end via Playwright with the real 18-02 endpoints**
## Performance
- **Duration:** ~15 min
- **Started:** 2026-06-15T02:30:00Z
- **Completed:** 2026-06-15T02:45:03Z
- **Tasks:** 3 (2 auto + 1 playwright-verified checkpoint)
- **Files modified/created:** 3
## Accomplishments
- Added `AdminTimezoneResponse` interface + `fetchAdminTimezone()` + `setAdminTimezone()` to `apps/pwa/src/api/client.ts`, following the exact pattern of `fetchAdminCalendars` / `setSharedCalendar` (credentials: include, redirect: manual, handleAuthResponse)
- Added Timezone section to `AdminPage.tsx` after the Shared Calendar section (with `marginBottom` on the preceding section for spacing)
- Timezone section features: 4-state loading/error/data pattern; `` + `