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 import
- api/src/modules/map/geocoding/ - Multi-provider geocoding service
- api/src/modules/map/cuts/ - Polygon CRUD + spatial queries
- api/src/modules/map/shifts/ - Shift CRUD + signups
- api/src/modules/map/canvass/ - Session + visit tracking
- api/src/modules/map/tracking/ - GPS tracking (future)
- api/src/modules/map/settings/ - Map settings singleton
Services:
- api/src/services/geocoding.service.ts - Geocoding abstraction
- api/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 tracking
- Cut - Name, GeoJSON polygon
- Shift - Date/time, cut, capacity, signups
- CanvassSession - Session tracking, start/end times
- CanvassVisit - Visit outcomes, notes, GPS
- MapSettings - Map center/zoom, walk sheet config
Frontend Components¶
Admin Pages:
- admin/src/pages/LocationsPage.tsx - Location management
- admin/src/pages/CutsPage.tsx - Cut management
- admin/src/pages/ShiftsPage.tsx - Shift management
- admin/src/pages/CanvassDashboardPage.tsx - Canvass monitoring
- admin/src/pages/WalkSheetPage.tsx - Printable materials
- admin/src/pages/DataQualityDashboardPage.tsx - Quality metrics
Public Pages:
- admin/src/pages/public/MapPage.tsx - Public map
- admin/src/pages/public/ShiftsPage.tsx - Shift signup
Volunteer Pages:
- admin/src/pages/volunteer/VolunteerMapPage.tsx - GPS canvass map
- admin/src/pages/volunteer/VolunteerShiftsPage.tsx - Assignments
- admin/src/pages/volunteer/MyActivityPage.tsx - Activity history
Map Components:
- admin/src/components/map/MapControls.tsx - Control buttons
- admin/src/components/map/AddLocationMode.tsx - Click-to-add
- admin/src/components/map/CutDrawingMode.tsx - Polygon drawing
- admin/src/components/map/CutOverlays.tsx - GeoJSON rendering
Canvass Components:
- admin/src/components/canvass/GPSTracker.tsx - GPS tracking
- admin/src/components/canvass/WalkingRouteLine.tsx - Route display
- admin/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: 1. Scan NAR data directory 2. List available provinces 3. Stream Address + Location files 4. Join on LOC_GUID 5. Transform coordinates (proj4) 6. 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: 1. Start at closest location to shift start point 2. For each location: - Find nearest unvisited location - Add to route - Mark as visited 3. 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