Files
HIPCTF2/.kilo/plans/890.md
T
2026-07-22 15:10:59 +00:00

27 lines
4.7 KiB
Markdown

# Implementation Plan: Admin Area General Settings UTC Datetime Round-Trip
## 1. Architectural Reconnaissance
- **Codebase style & conventions:** TypeScript monorepo with an Angular 17 standalone SPA and NestJS backend. The General Settings screen uses a strictly typed, non-nullable reactive form in `frontend/src/app/features/admin/general.component.ts`, while reusable formatting and validation logic is extracted to pure functions in `frontend/src/app/features/admin/general.pure.ts`. The component loads backend ISO timestamps through `toDatetimeLocal`, submits form values through `toIsoUtc`, and uses async/await around the promise-based `AdminService` API facade.
- **Data Layer:** NestJS persists general settings as string key/value rows through `SettingsService`. `AdminGeneralService.updateSettings` writes `eventStartUtc` and `eventEndUtc` verbatim after `GeneralSettingsSchema` validates timezone-aware ISO-8601 strings and strict start/end ordering. No database schema or migration is required; the defect is isolated to frontend conversion of UTC-labelled `datetime-local` values.
- **Test Framework & Structure:** Root Jest 29 multi-project configuration with `ts-jest`; frontend tests run in jsdom from the dedicated `tests/frontend/` folder. `npm test` runs backend and frontend projects together, while `npm run test:frontend` runs the focused frontend project. Existing pure-helper coverage is in `tests/frontend/admin-general-pure.spec.ts`, which is the appropriate lightweight regression location and requires no browser UI.
- **Required Tools & Dependencies:** No new system tools, global CLI utilities, package dependencies, persistent `/data` assets, or `setup.sh` changes are required. The implementation uses built-in JavaScript `Date` UTC construction/serialization and the existing Jest toolchain.
## 2. Impacted Files
- **To Modify:**
- `frontend/src/app/features/admin/general.pure.ts` — make `toIsoUtc` interpret the numeric components of the UTC-labelled `datetime-local` string as UTC rather than as the browser's local timezone.
- `tests/frontend/admin-general-pure.spec.ts` — add a focused timezone regression proving the displayed UTC wall-clock components serialize unchanged and preserve existing empty/invalid behavior.
- **To Create:** None.
## 3. Proposed Changes
1. **Database / Schema Migration:** No changes. The existing setting keys and backend zod schema already accept and persist canonical UTC ISO strings correctly.
2. **Backend Logic & APIs:** No changes. `PUT /api/v1/admin/general/settings` already validates timezone-aware ISO-8601 input, enforces `eventEndUtc > eventStartUtc`, and stores the payload without timezone conversion; `GET /api/v1/event/status` therefore reflects whatever canonical instant the frontend sends.
3. **Frontend UI Integration:**
1. Update `toIsoUtc` in `general.pure.ts` to parse the `datetime-local` year, month, day, hour, minute, and optional second/fraction components as UTC components, then create the timestamp with `Date.UTC(...)` and return `toISOString()`.
2. Preserve the helper's current contract for empty values (`''`) and invalid values (return the original string), so the existing reactive-form validation and negative save paths remain unchanged.
3. Keep `toDatetimeLocal` unchanged because it already renders backend timestamps from UTC getters. Together, `toDatetimeLocal(iso)` and `toIsoUtc(local)` will become true timezone-independent inverses for the minute-precision native inputs used by `AdminGeneralComponent`.
4. Keep `AdminGeneralComponent.onSubmit` and the service/API contract unchanged; both event fields already pass through `toIsoUtc`, so correcting the shared helper fixes start and end submissions without UI or backend rewiring.
## 4. Test Strategy
- **Target Unit Test File:** `tests/frontend/admin-general-pure.spec.ts`.
- **Mocking Strategy:** No external boundaries need mocking because the defect is entirely in a pure function. Add a minimal deterministic regression around `toIsoUtc('2027-03-15T08:30') === '2027-03-15T08:30:00.000Z'` and the corresponding end value `2027-03-17T16:45`, explicitly exercising the America/Los_Angeles/PDT scenario without launching a UI. Prefer running the focused Jest process with `TZ=America/Los_Angeles` (or isolate a small child Jest invocation configured with that environment) so the test fails against the current local-time implementation and passes only when conversion is browser-timezone independent. Retain or extend the existing empty-input assertion and add only the key invalid-input assertion if needed to lock the helper's fallback contract. Verify with the root single-command suite (`npm test`) plus the existing root build/type-check path (`npm run build`); no visual confirmation or persistent test data is involved.