10 KiB
Map Module
The Map module provides comprehensive location management, geographic organization, volunteer coordination, and door-to-door canvassing capabilities. It combines GIS features with volunteer management for effective ground campaigns.
Overview
The Map module consists of ten integrated components:
- Locations - Location database with geocoding
- Geocoding - Multi-provider address → coordinate conversion
- NAR Import - Canadian electoral data import
- Cuts - Geographic polygon organization
- Shifts - Volunteer shift scheduling
- Canvassing - Door-to-door canvassing system
- Tracking - GPS tracking sessions
- Walk Sheets - Printable canvass materials
- Data Quality - Geocoding quality monitoring
- Map Features Status - Feature completion tracking
Features
Location Management
- Location CRUD with address, coordinates, metadata
- CSV import/export (100,000+ records supported)
- Multi-provider geocoding (6 providers)
- Bulk geocoding with queue
- NAR 2025 server-side import (Canadian electoral data)
- Address standardization
- Visit tracking integration
Geographic Organization
- Polygon-based geographic cuts
- GeoJSON import/export
- Point-in-polygon queries
- Cut-based location assignment
- Spatial bounds calculation
- Map visualization
Volunteer Coordination
- Shift scheduling with cut assignment
- Volunteer signup (authenticated + anonymous)
- Email confirmations
- Temp user creation for walk-ins
- Shift capacity tracking
Canvassing System
- GPS-enabled mobile interface
- Walking route algorithm (nearest-neighbor)
- Visit outcome recording (7 outcomes)
- Session management (start/end/abandon)
- Real-time progress tracking
- Admin monitoring dashboard
- Printable walk sheets with QR codes
Map Display
- Public interactive Leaflet map
- Color-coded markers by visit status
- Polygon overlays for cuts
- Geolocate button
- Fullscreen mode
- Legend and controls
User Flow
Admin Experience
-
Import Locations (
/app/map/locations)- Upload CSV or NAR data
- Geocode addresses
- Review quality metrics
- Bulk operations
-
Create Cuts (
/app/map/cuts)- Draw polygons on map
- Name and describe cut
- Assign locations (automatic)
- Export for printing
-
Schedule Shifts (
/app/map/shifts)- Create shift with cut assignment
- Set date/time/capacity
- Email all volunteers
- Monitor signups
-
Monitor Canvassing (
/app/canvass/dashboard)- View active sessions
- Track visit progress
- Check leaderboard
- Review activity feed
-
Print Materials (
/app/canvass/walk-sheet)- Select cut
- Generate walk sheet PDF
- QR codes for quick access
- Browser print
Volunteer Experience
-
View Assignments (
/volunteer/assignments)- See upcoming shifts
- Cut information
- Start canvass button
-
Canvass (
/volunteer/canvass/:cutId)- Full-screen map with GPS
- Follow walking route
- Click markers to record visits
- Select outcomes + notes
- Track progress
-
Review Activity (
/volunteer/activity)- Visit history
- Outcome breakdown
- Session statistics
Public Experience
-
View Map (
/map)- Browse locations
- View cuts
- See visit status (color-coded)
- Geolocate self
-
Sign Up for Shifts (
/shifts)- Browse available shifts
- Signup with email
- Receive confirmation
Architecture
Backend Components
Modules:
api/src/modules/map/locations/- Location CRUD + geocoding + NAR importapi/src/modules/map/geocoding/- Multi-provider geocoding serviceapi/src/modules/map/cuts/- Polygon CRUD + spatial queriesapi/src/modules/map/shifts/- Shift CRUD + signupsapi/src/modules/map/canvass/- Session + visit trackingapi/src/modules/map/tracking/- GPS tracking (future)api/src/modules/map/settings/- Map settings singleton
Services:
api/src/services/geocoding.service.ts- Geocoding abstractionapi/src/services/geocode-queue.service.ts- Async geocoding
Utilities:
api/src/utils/spatial.ts- Point-in-polygon, haversine, bounds, centroid
Database Models:
Location- Address, coordinates, metadata, visit trackingCut- Name, GeoJSON polygonShift- Date/time, cut, capacity, signupsCanvassSession- Session tracking, start/end timesCanvassVisit- Visit outcomes, notes, GPSMapSettings- Map center/zoom, walk sheet config
Frontend Components
Admin Pages:
admin/src/pages/LocationsPage.tsx- Location managementadmin/src/pages/CutsPage.tsx- Cut managementadmin/src/pages/ShiftsPage.tsx- Shift managementadmin/src/pages/CanvassDashboardPage.tsx- Canvass monitoringadmin/src/pages/WalkSheetPage.tsx- Printable materialsadmin/src/pages/DataQualityDashboardPage.tsx- Quality metrics
Public Pages:
admin/src/pages/public/MapPage.tsx- Public mapadmin/src/pages/public/ShiftsPage.tsx- Shift signup
Volunteer Pages:
admin/src/pages/volunteer/VolunteerMapPage.tsx- GPS canvass mapadmin/src/pages/volunteer/VolunteerShiftsPage.tsx- Assignmentsadmin/src/pages/volunteer/MyActivityPage.tsx- Activity history
Map Components:
admin/src/components/map/MapControls.tsx- Control buttonsadmin/src/components/map/AddLocationMode.tsx- Click-to-addadmin/src/components/map/CutDrawingMode.tsx- Polygon drawingadmin/src/components/map/CutOverlays.tsx- GeoJSON rendering
Canvass Components:
admin/src/components/canvass/GPSTracker.tsx- GPS trackingadmin/src/components/canvass/WalkingRouteLine.tsx- Route displayadmin/src/components/canvass/VisitRecordingForm.tsx- Outcome form
Configuration
Environment Variables
# Geocoding Providers
MAPBOX_ACCESS_TOKEN=pk_...
GOOGLE_GEOCODE_API_KEY=...
PELIAS_API_URL=http://pelias:4000
# NAR Import
NAR_DATA_DIR=/data # NAR file directory (Docker volume)
# Map Settings
MAP_DEFAULT_LAT=43.65 # Default map center
MAP_DEFAULT_LNG=-79.38
MAP_DEFAULT_ZOOM=12
Map Settings
Configurable via admin UI (/app/map/settings):
- Default map center (lat/lng)
- Default zoom level
- Walk sheet header/footer
- Display preferences
Geocoding
Supported Providers
- Nominatim (OpenStreetMap) - Free, rate limited
- ArcGIS - Free tier available
- Photon - Free, self-hosted option
- Mapbox - API key required
- Google Geocoding - API key required
- Pelias - Self-hosted option
Geocoding Strategy
- Try provider 1 (Nominatim)
- If fails, try provider 2 (ArcGIS)
- Continue through providers
- Cache successful results
- Track quality metrics
Bulk Geocoding
- BullMQ queue for async processing
- Batch processing (100 locations/batch)
- Provider rotation to avoid rate limits
- Progress tracking
- Error handling and retry
NAR Import
Canadian electoral data (NAR 2025 format):
- Address files - Civic addresses with coordinates (EPSG:3347)
- Location files - Building locations with lat/lng
- Join on LOC_GUID - Combine address + coordinates
- Server-side streaming - Memory-efficient for large files
- Filters - Province, city, postal code, cut, residential-only
Import Flow:
- Scan NAR data directory
- List available provinces
- Stream Address + Location files
- Join on LOC_GUID
- Transform coordinates (proj4)
- Filter and insert locations
Spatial Algorithms
Point-in-Polygon
Ray-casting algorithm:
- Count ray intersections with polygon edges
- Odd count = inside, even count = outside
- Supports holes in polygons
- Used for cut assignment
Walking Route
Nearest-neighbor algorithm:
- Start at closest location to shift start point
- For each location:
- Find nearest unvisited location
- Add to route
- Mark as visited
- Return ordered list
Haversine Distance
Great-circle distance between coordinates:
- Returns distance in kilometers
- Used for proximity sorting
- Route optimization
API Endpoints
Locations
GET /api/locations # List locations
POST /api/locations # Create location
GET /api/locations/:id # Get location
PATCH /api/locations/:id # Update location
DELETE /api/locations/:id # Delete location
POST /api/locations/import # CSV import
GET /api/locations/export # CSV export
POST /api/locations/geocode # Bulk geocode
Cuts
GET /api/cuts # List cuts
POST /api/cuts # Create cut
GET /api/cuts/:id # Get cut
PATCH /api/cuts/:id # Update cut
DELETE /api/cuts/:id # Delete cut
POST /api/cuts/:id/assign-locations # Assign locations
Shifts
GET /api/shifts # List shifts
POST /api/shifts # Create shift
GET /api/shifts/:id # Get shift
PATCH /api/shifts/:id # Update shift
DELETE /api/shifts/:id # Delete shift
POST /api/shifts/:id/signup # Signup for shift
Canvassing
POST /api/canvass/session/start # Start session
POST /api/canvass/session/end # End session
GET /api/canvass/session # Get active session
POST /api/canvass/visit # Record visit
GET /api/canvass/route/:cutId # Get walking route
GET /api/canvass/dashboard # Dashboard stats