Files
motovaultpro/backend/src/features/stations/README.md
2025-11-04 18:46:46 -06:00

6.8 KiB

Gas Stations Feature

Complete gas station discovery and management feature with Google Maps integration, caching, and user favorites.

Quick Summary

Search nearby gas stations via Google Maps API. Users can view stations on a map, save favorites with custom notes, and integrate station data into fuel logging. Search results cached for 1 hour. JWT required for all endpoints. User data isolation via user_id.

Implementation Phases Status

Phase Feature Status
1 Frontend K8s-aligned secrets pattern Complete
2 Backend improvements (circuit breaker, tests) Complete
3 Frontend foundation (types, API, hooks) Complete
4 Frontend components (card, list, form, map) Complete
5 Desktop page with map/search layout Complete
6 Mobile screen with tab navigation 🔄 In Progress
7 Fuel logs integration (StationPicker) Pending
8 Testing (unit, integration, E2E) Pending
9 Documentation (API, setup, troubleshooting) Pending
10 Validation & Polish (lint, tests, manual) Pending
11 Deployment preparation & checklist Pending

Architecture

Backend Structure

features/stations/
├── api/                        # HTTP handlers and routes
│   ├── stations.controller.ts
│   └── stations.routes.ts
├── domain/                     # Business logic
│   ├── stations.service.ts
│   └── stations.types.ts
├── data/                       # Database access
│   └── stations.repository.ts
├── external/google-maps/       # External API
│   ├── google-maps.client.ts
│   ├── google-maps.circuit-breaker.ts
│   └── google-maps.types.ts
├── jobs/                       # Scheduled tasks
│   └── cache-cleanup.job.ts
├── migrations/                 # Database schema
│   ├── 001_create_stations_tables.sql
│   └── 002_add_indexes.sql
├── tests/                      # Test suite
│   ├── fixtures/
│   ├── unit/
│   └── integration/
└── index.ts                    # Feature exports

Frontend Structure

features/stations/
├── types/                      # TypeScript definitions
│   └── stations.types.ts
├── api/                        # API client
│   └── stations.api.ts
├── hooks/                      # React Query hooks
│   ├── useStationsSearch.ts
│   ├── useSavedStations.ts
│   ├── useSaveStation.ts
│   ├── useDeleteStation.ts
│   └── useGeolocation.ts
├── utils/                      # Utilities
│   ├── distance.ts
│   ├── maps-loader.ts
│   └── map-utils.ts
├── components/                 # React components
│   ├── StationCard.tsx
│   ├── StationsList.tsx
│   ├── SavedStationsList.tsx
│   ├── StationsSearchForm.tsx
│   └── StationMap.tsx
├── pages/                      # Page layouts
│   └── StationsPage.tsx        # Desktop
├── mobile/                     # Mobile layouts (Phase 6)
│   └── StationsMobileScreen.tsx
└── __tests__/                  # Tests (Phase 8)

API Endpoints (All require JWT)

POST /api/stations/search
  Body: { latitude, longitude, radius?, fuelType? }
  Response: { stations[], searchLocation, searchRadius, timestamp }

POST /api/stations/save
  Body: { placeId, nickname?, notes?, isFavorite? }
  Response: SavedStation

GET /api/stations/saved
  Response: SavedStation[]

GET /api/stations/saved/:placeId
  Response: SavedStation | 404

PATCH /api/stations/saved/:placeId
  Body: { nickname?, notes?, isFavorite? }
  Response: SavedStation

DELETE /api/stations/saved/:placeId
  Response: 204

Database Schema

station_cache

Temporary Google Places results (auto-cleanup after 24h)

- id: UUID PRIMARY KEY
- place_id: VARCHAR UNIQUE
- name: VARCHAR
- address: VARCHAR
- latitude: DECIMAL
- longitude: DECIMAL
- rating: DECIMAL
- photo_url: VARCHAR
- created_at: TIMESTAMP

saved_stations

User's favorite stations with metadata

- id: UUID PRIMARY KEY
- user_id: VARCHAR (indexed)
- place_id: VARCHAR (indexed)
- nickname: VARCHAR
- notes: TEXT
- is_favorite: BOOLEAN
- created_at: TIMESTAMP
- updated_at: TIMESTAMP
- deleted_at: TIMESTAMP (soft delete)
- UNIQUE(user_id, place_id)

Key Features Implemented

Security

  • User-scoped data isolation via user_id filtering
  • Parameterized queries (no SQL injection)
  • JWT authentication required on all endpoints
  • K8s-aligned secrets pattern (never in environment variables)

Performance

  • Redis caching with 1-hour TTL
  • Circuit breaker for resilience (10s timeout, 50% threshold)
  • Database indexes on user_id and place_id
  • Scheduled cache cleanup (24h auto-expiry)
  • Lazy-loaded Google Maps API in browser

User Experience

  • Real-time browser geolocation with permission handling
  • Touch-friendly 44px minimum button heights
  • Responsive map with auto-fit bounds
  • Saved stations with custom nicknames and notes
  • One-click directions to Google Maps

Testing

Run Tests

# Backend feature tests
cd backend
npm test -- features/stations

# Frontend component tests (Phase 8)
cd frontend
npm test -- stations

# E2E tests (Phase 8)
npm run e2e

Coverage Goals

  • Backend: >80% coverage
  • Frontend components: >80% coverage
  • All critical paths tested

Deployment

Prerequisites

  1. Google Maps API key with Places API enabled
  2. PostgreSQL database with migrations applied
  3. Redis cache service running
  4. Docker for containerization

Setup

# Create secrets directory
mkdir -p ./secrets/app

# Add Google Maps API key
echo "YOUR_API_KEY_HERE" > ./secrets/app/google-maps-api-key.txt

# Build and start
make setup
make logs

# Verify
curl http://localhost:3001/health

Verification

# Check secrets mounted
docker compose exec mvp-frontend cat /run/secrets/google-maps-api-key

# Check config generated
docker compose exec mvp-frontend cat /usr/share/nginx/html/config.js

# Test API endpoint
curl -H "Authorization: Bearer $TOKEN" http://localhost:3001/api/stations/saved

Next Steps (Phases 6-11)

Phase 6: Mobile Implementation

Create mobile bottom-tab navigation screen with Search, Saved, Map tabs.

Phase 7: Fuel Logs Integration

Add StationPicker component with autocomplete to FuelLogForm.

Phases 8-11: Testing, Docs, Validation, Deployment

Follow the detailed plan in /docs/GAS-STATIONS.md.

References

  • Full implementation plan: /docs/GAS-STATIONS.md
  • Runtime config pattern: /frontend/docs/RUNTIME-CONFIG.md
  • Design patterns: See Platform feature (backend/src/features/platform/)
  • Component patterns: See Vehicles feature (frontend/src/features/vehicles/)