Commit graph

12 commits

Author SHA1 Message Date
Ullrich Schäfer
bd311cd339
Implement mobile route editor with MapLibre and BRouter routing
Route editing (Phase 3.3):
- useRouteEditor hook: waypoint state, add/move/delete, BRouter
  routing via Journal API proxy, GPX generation, save to API
- RouteMap component: MapLibre Native with OSM raster tiles,
  route polyline (ShapeSource + LineLayer), waypoint markers
  (MarkerView), long-press to add waypoints, computing indicator
- WaypointSheet: bottom sheet for waypoint actions — delete with
  confirmation, overnight stop toggle, coordinates display
- Route detail screen: view mode (map preview + stats) and edit
  mode (full-screen map with save button)
- Unsaved changes guard on navigation (beforeRemove listener)
- Smart waypoint insertion at nearest route segment
- Waypoint extraction from GPX via regex (sync, no DOM needed)

Adds DOM.Iterable to mobile tsconfig for gpx package compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 01:06:10 +02:00
Ullrich Schäfer
204fd7084b
Configure EAS Build and fix expo-doctor issues
- Add eas.json with development, preview, and production profiles
- Link project to EAS (projectId: 93c75cae-fecf-4ce5-8cd8-c823760b12e2)
- Add expo-dev-client, expo-constants, expo-linking dependencies
- Remove eas-cli from project deps (use globally)
- Add ITSAppUsesNonExemptEncryption to iOS infoPlist
- Use catalog react with expo.install.exclude to skip version check
- Fix slug to match EAS project registration
- Run pnpm dedupe to resolve duplicate react across workspaces

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 01:35:15 +02:00
Ullrich Schäfer
2f99ce926a
Add route detail screen with metadata and action buttons
Route detail at /routes/:id shows:
- Header with back navigation and route name
- Map placeholder (MapLibre requires EAS dev build)
- Stats row: distance, elevation gain/loss, day count
- Description text
- Version count
- "Edit in Planner" opens Journal web UI
- "Download Offline" button (handler pending Phase 5)

Safe area insets applied to header and scroll content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 01:15:41 +02:00
Ullrich Schäfer
77e3c1b1ee
Build Routes tab with paginated list and Zod-validated API responses
Routes tab (Phase 3.1):
- Paginated FlatList fetching from Journal REST API
- Route cards with name, distance (km), elevation gain, day count
- Pull-to-refresh, loading spinner, error state with retry, empty state
- Safe area insets for notch and tab bar

API client:
- Import types from @trails-cool/api instead of hand-written interfaces
- Parse list/detail responses through Zod schemas at runtime
- Add zod as mobile app dependency

i18n:
- Add mobile namespace (en + de) for routes, activities, profile, login

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 01:15:40 +02:00
Ullrich Schäfer
18c3c37eaf
Implement Journal REST API v1 endpoints
Add all REST API endpoints for mobile app consumption:

Routes:
- GET /api/v1/routes — paginated list with cursor, Zod validation
- GET /api/v1/routes/:id — full detail with GPX, versions
- POST /api/v1/routes — create with Zod-validated body
- PUT /api/v1/routes/:id — update, creates new version
- DELETE /api/v1/routes/:id — returns 204

Activities:
- GET /api/v1/activities — paginated list with cursor
- GET /api/v1/activities/:id — full detail
- POST /api/v1/activities — create with GPX stat extraction
- DELETE /api/v1/activities/:id — returns 204

Supporting:
- POST /api/v1/routes/compute — BRouter proxy
- POST /api/v1/uploads — presigned upload URL generation

Device management:
- GET /api/v1/auth/devices — list connected devices with isCurrent
- DELETE /api/v1/auth/devices/:id — revoke device token
- Store device_name on token exchange

Infrastructure:
- requireApiUser() guard — returns 401 with structured error
- apiError() helper for consistent error responses
- All endpoints use Zod schemas from @trails-cool/api for validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:57:27 +02:00
Ullrich Schäfer
1ae406a8aa
Implement OAuth2 PKCE auth, discovery, and mobile API client
Journal server (Phase 1.4 + 1.5):
- Add oauth_clients, oauth_codes, oauth_tokens tables to journal schema
- Implement GET /oauth/authorize with PKCE flow and login redirect
- Implement POST /oauth/token (authorization_code + refresh_token grants)
- Add validateBearerToken() + getAuthenticatedUser() middleware
- Seed trails-cool-mobile as trusted OAuth client on server startup
- Add GET /.well-known/trails-cool discovery endpoint
- Add returnTo support to login page and magic link verify
- Add @trails-cool/api workspace dependency to journal

Mobile app (Phase 1.5 + 1.6):
- Login screen with server URL input and discovery validation
- OAuth2 PKCE login via expo-web-browser with expo-crypto for Hermes
- Token storage in expo-secure-store with auto-refresh on 401
- API client with bearer token injection and typed errors
- Server URL persistence with localhost default in dev mode
- API version compatibility check on app foreground
- Log out + switch server on Profile tab
- iOS ATS exception for local networking

Tests:
- PKCE crypto verification, OAuthError, token generation
- Discovery endpoint response shape
- API version semver compatibility
- API client error types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:41:40 +02:00
Ullrich Schäfer
2ac4014521
Standardize monorepo pipeline: test, lint, typecheck across all workspaces
Previously only 2-3 workspaces participated in each turbo task. This
expands test, lint, and typecheck to cover all 11 workspaces with
parallel execution and caching.

Test pipeline:
- Move from single root vitest to per-workspace test scripts via turbo
- Shared vitest config (vitest.shared.ts) with passWithNoTests
- Per-workspace configs re-export the shared base
- Mobile uses Jest (jest-expo + React Native Testing Library)
- Add node-environment GPX tests verifying linkedom fallback
- Add i18n mobile init tests
- Exclude apps/mobile from root vitest (uses Jest separately)

Lint pipeline:
- Add eslint lint script to all 9 previously unlinted workspaces
- Standardize all scripts to "eslint ." with shared root config
- Add .expo/ to global ESLint ignores
- Fix lint errors: unused imports in api/types, export parseGpx

Typecheck pipeline:
- Add "typecheck": "tsc" to all 8 packages
- Add @types/node (catalog) to gpx and db packages
- Fix mobile app.config.ts: remove deprecated experiments.monorepo
  and newArchEnabled (both default in Expo SDK 55)
- Add allowImportingTsExtensions to mobile tsconfig

Shared package compatibility (mobile-app Phase 1.3):
- Add linkedom as explicit dependency to @trails-cool/gpx
- Add initI18nMobile() export to @trails-cool/i18n
- Confirm @trails-cool/types is pure interfaces (no DOM deps)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 00:00:43 +02:00
Ullrich Schäfer
95fdbfee2f
Initialize Expo mobile app with tab navigation and monorepo support
- Expo managed project at apps/mobile/ with TypeScript
- Expo Router with 4 tabs: Map, Routes, Activities, Profile
- app.config.ts with monorepo experiment, bundle IDs, scheme
- Workspace packages linked: api, gpx, i18n, map-core, types
- Profile tab imports API_VERSION from @trails-cool/api to verify
  shared package resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:05:57 +02:00
Ullrich Schäfer
48f990f4ec
Mark Phase 1.2 API Contract Package tasks as complete
@trails-cool/api shipped in PR #214 — Zod schemas, endpoint constants,
API_VERSION, error types, pagination, auth, routes, activities, uploads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:59:13 +02:00
Ullrich Schäfer
572d240ed1
Fix all openspec validation errors (45/45 pass)
Main specs (7): Converted from delta format (## ADDED/MODIFIED) to
proper main spec format (## Purpose + ## Requirements)

Changes (3): Added missing spec files for e2e-test-reorganization,
journal-poi-details, and mobile-nearby-sync

Mobile testing: Added missing scenario for "No Vitest" requirement

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:41:51 +02:00
Ullrich Schäfer
cd939ccf07
Complete mobile app specs: fill all gaps
Design fixes:
- D6: Cleaned up, points to separate activity-recording change
- D13: Locked in TanStack Query + Zustand + React Context
- D14: Tile hosting (OpenFreeMap default, configurable tileUrl)
- D15: Photo/media (presigned upload URLs, thumbnails)
- D16: Journal REST API implementation (api.v1.*.ts route modules)

New specs (4):
- web-push-relay: Web Push → APNs/FCM relay (Mastodon pattern)
- api-contract-package: @trails-cool/api with Zod schemas
- device-management: Connected devices list + revoke
- photo-media: Presigned uploads, thumbnails, photo display

Task updates:
- Added Phase 2: Journal REST API (16 tasks)
- Added Phase 7: Notifications (8 tasks)
- Renumbered all phases (1-7)
- 112 total tasks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:12:54 +02:00
Ullrich Schäfer
fff77a2ed2
Add mobile app, map-core, nearby sync, and activity recording specs
mobile-app: Unified React Native + Expo app combining Planner and
Journal. OAuth2 PKCE auth, MapLibre maps, versioned REST API with
Zod schemas, configurable server URL, offline SQLite, Web Push relay
notifications. TanStack Query + Zustand state management. Jest +
Maestro testing. 76 tasks across 5 phases.

map-core-package: Extract renderer-agnostic map definitions (tiles,
color palettes, POI categories, z-index) into @trails-cool/map-core.
Pure refactor preparing for MapLibre on mobile. 27 tasks.

mobile-activity-recording: GPS recording, live stats, HealthKit/Health
Connect export. Separated from mobile-app for independent scheduling.

mobile-nearby-sync: BLE route sync between nearby devices for offline
group riding. QR waypoint sharing as simpler v1. TXQR noted as future.

journal-rest-api spec: Full API contract — endpoints, auth, pagination,
errors, discovery, versioning, BRouter proxy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:52:30 +02:00