Commit Graph

2 Commits

Author SHA1 Message Date
julian bc54f1e811 feat: task 2.2 tile-source switcher
- pnpm add maplibre-google-maps (runtime; lazy-imported on Google use).
- src/map/core/styles.ts: BasemapDescriptor model with four entries
  (Esri Satellite / OpenTopoMap / OSM / Google Satellite).
  Google entry gated on cfg.googleMapsKey via available(cfg).
  styleCustom() builds a single-raster-source MapLibre style with a
  glyphs URL for future label rendering.
  ensureGoogleProtocol() lazy-loads maplibre-google-maps + addProtocol
  on first use; _googleRegistered guards re-registration.
- src/map/core/map-pref-store.ts: Zustand + persist middleware
  (key: trm-map-prefs, version: 1). Holds basemapId + setBasemap.
- src/map/core/basemap-switcher.tsx: floating control top-right of
  <MapView>. Filters by available(cfg), highlights active, applies via
  getMap().setStyle(). Mount-time bootstrap (no UI state) + user-driven
  onClick (with switching state) split to satisfy React 19's
  react-hooks/set-state-in-effect rule.
- src/routes/_authed/monitor.tsx: renders <BasemapSwitcher /> as a
  child of <MapView>.
- src/vite-env.d.ts: ambient module declaration for
  maplibre-google-maps (no .d.ts ships in the package).

Deviations:
- BasemapDescriptor.style is buildStyle(cfg): StyleSpecification, not
  the spec's StyleSpecification|string union. Google needs the cfg key
  at build time; uniform function shape across all entries is cleaner.
- Bootstrap apply path doesn't use the switching UI state (no visual
  feedback needed during the silent first-paint flip from OSM to user
  preference). User-click path keeps setSwitching for the in-flight
  indicator.

Bundle: MapLibre is now its own chunk (1MB / 273KB gz), shared across
maplibre consumers. Main bundle 371KB / 114KB gz.
2026-05-03 09:29:14 +02:00
julian 8d0bc2bb1e feat(login): dev-only prefill from VITE_ADMIN_EMAIL/PASSWORD
When import.meta.env.DEV is true, the login form's email and password
fields are populated from the corresponding env vars. Shaves the manual
re-typing during dev iteration.

Production builds get empty strings regardless of build-time env values:
the prefill is gated on import.meta.env.DEV (which Vite replaces with
literal `false` at build time, so the surrounding ternary tree-shakes
and the env values can't bleed into the prod bundle even if accidentally
set in the build env).

Files:
- src/vite-env.d.ts (new): ImportMetaEnv augmentation with the four
  VITE_* vars we use (admin email/password, dev directus/processor URLs).
  Gives proper typing under strict mode.
- src/ui/pages/login.tsx: devDefaults computed once at module scope from
  import.meta.env. Form's defaultValues uses it.
- .env.example: documents VITE_ADMIN_EMAIL and VITE_ADMIN_PASSWORD with
  examples; notes the prod-ignore guarantee.
- .gitignore: adds *.env (defensive — complements the existing *.local
  pattern). .env.example stays committable (doesn't end in .env).
2026-05-02 18:48:04 +02:00