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

4.7 KiB

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.