# NocoDB Map V- 🔒 Secure API proxy to protect credentials
- 👤 User authentication with login system
- ⚙️ Admin panel for system configuration
- 🎯 Configurable map start location
- 📋 Walk Sheet generator for door-to-door canvassing
- 🔗 QR code integration for digital resources
- 📅 Volunteer shift management system with calendar and grid views
- ✋ User shift signup and cancellation with color-coded calendar
- 📅 Calendar integration (Google, Outlook, Apple) for shift export
- 👥 Admin shift creation and management with volunteer assignment
- 📧 **Automated shift email notifications** - Send shift details to volunteers with visual progress tracking
- 👨‍💼 User management panel for admin users (create, delete users)
- 📧 **Admin broadcast emailing** - Rich HTML email composer with live preview and delivery tracking
- 📧 **Listmonk Integration** - Real-time sync with self-hosted newsletter platform for advanced email marketing
- 🔐 Role-based access control (Admin vs User permissions)Automated shift email notifications** - Send shift details to volunteers with visual progress tracking
- �👨‍💼 User management panel for admin users (create, delete users)
- � **Admin broadcast emailing** - Rich HTML email composer with live preview and delivery trackingntainerized web application that visualizes geographic data from NocoDB on an interactive map using Leaflet.js.

## Features

- 🗺️ Interactive map visualization with OpenStreetMap
- 🔍 **Unified search system with docs and address search** (Ctrl+K to activate)
- 📍 Real-time geolocation support
- ➕ Add new locations directly from the map
- 🔄 Auto-refresh every 30 seconds
- 📱 Responsive design for mobile devices
- 🔒 Secure API proxy to protect credentials
- 👤 User authentication with login system
- ⚙️ Admin panel for system configuration
- 🎯 Configurable map start location
- 📋 Walk Sheet generator for door-to-door canvassing
- 🔗 QR code integration for digital resources
- 📅 Volunteer shift management system with calendar and grid views
- ✋ User shift signup and cancellation with color-coded calendar
- 🌐 **Public shift signup** - Share volunteer opportunities with visitors (no account required)
- 🔗 **Direct shift links** - Generate shareable URLs for specific volunteer opportunities
- 👤 **Auto account creation** - Temporary accounts created automatically during public signup
- 📅 Calendar integration (Google, Outlook, Apple) for shift export
- 👥 Admin shift creation and management with volunteer assignment
- 📧 **Automated shift email notifications** - Send shift details to volunteers
- �👨‍💼 User management panel for admin users (create, delete users)
- � **Admin broadcast emailing** - Rich HTML email composer with live preview
- �🔐 Role-based access control (Admin vs User permissions)
- ⏰ Temporary user accounts with automatic expiration
- 📧 Email notifications and password recovery via SMTP
- 📊 **Enhanced CSV data import** with multi-provider geocoding, confidence scoring, and comprehensive error reporting
- 🌍 **Multi-provider geocoding system** - Mapbox (premium), Nominatim, Photon, LocationIQ, and ArcGIS with automatic fallback
- 🎯 **Geocoding confidence scoring** - Quality assessment and validation warnings for all geocoded addresses
- 🔍 **Database scan and geocode** - Admin tool to scan existing records and geocode missing location data
- 📈 **Comprehensive geocoding reports** - Downloadable CSV reports with success/failure analysis and recommendations
- ✂️ **Cut feature for geographic overlays** - Admin-drawn polygons for map regions
- 🗺️ Interactive polygon drawing with click-to-add-points system
- 🎨 Customizable cut properties (color, opacity, category, visibility)
- 🐳 Docker containerization for easy deployment
- 🆓 100% open source (no proprietary dependencies)

## Quick Start

### Prerequisites

- Docker and Docker Compose
- NocoDB instance with API access
- NocoDB API token

### Installation

1. **Get NocoDB API Token**

   1. Login to your NocoDB instance
   2. Click user icon → **Account Settings** → **API Tokens**
   3. Create new token with read/write permissions
   4. Copy the token for the next step

2. **Configure Environment**

   Create a `.env` file in the `map/` directory with your configuration:

   ```env
   # Core NocoDB Configuration
   NOCODB_API_URL=https://your-nocodb-instance.com/api/v1
   NOCODB_API_TOKEN=your-api-token-here
   NOCODB_VIEW_URL=https://your-nocodb-instance.com/dashboard/#/nc/project-id/table-id
   
   # Additional NocoDB Sheet URLs
   NOCODB_LOGIN_SHEET=https://your-nocodb-instance.com/dashboard/#/nc/project-id/login-table-id
   NOCODB_SETTINGS_SHEET=https://your-nocodb-instance.com/dashboard/#/nc/project-id/settings-table-id
   NOCODB_SHIFTS_SHEET=https://your-nocodb-instance.com/dashboard/#/nc/project-id/shifts-table-id
   NOCODB_SHIFT_SIGNUPS_SHEET=https://your-nocodb-instance.com/dashboard/#/nc/project-id/signups-table-id
   NOCODB_CUTS_SHEET=https://your-nocodb-instance.com/dashboard/#/nc/project-id/cuts-table-id
   
   # Server Configuration
   DOMAIN=your-domain.com
   PORT=3000
   NODE_ENV=production
   SESSION_SECRET=your-secure-session-secret-here
   
   # Map Defaults (adjust for your region)
   DEFAULT_LAT=53.5461
   DEFAULT_LNG=-113.4938
   DEFAULT_ZOOM=11
   
   # Enhanced Geocoding Configuration (Optional but Recommended)
   # Mapbox API Key for premium geocoding with highest accuracy
   MAPBOX_ACCESS_TOKEN=pk.your-mapbox-token-here
   
   # LocationIQ API Key for additional premium geocoding option
   # LOCATIONIQ_API_KEY=your-locationiq-key-here
   
   # SMTP Email Configuration
   SMTP_HOST=your-smtp-host.com
   SMTP_PORT=587
   SMTP_SECURE=false
   SMTP_USER=your-email@domain.com
   SMTP_PASS=your-email-password
   EMAIL_FROM_NAME="Your App Name"
   EMAIL_FROM_ADDRESS=your-email@domain.com
   
   # Optional: Listmonk Integration for Email Marketing
   LISTMONK_API_URL=http://your-listmonk-instance:9000/api
   LISTMONK_USERNAME=admin
   LISTMONK_PASSWORD=your-listmonk-password
   LISTMONK_SYNC_ENABLED=true
   ```
   # NocoDB API Configuration
   NOCODB_API_URL=https://db.cmlite.org/api/v1
   NOCODB_API_TOKEN=your-api-token-here

   # These will be populated after running build-nocodb.sh
   NOCODB_VIEW_URL=
   NOCODB_LOGIN_SHEET=
   NOCODB_SETTINGS_SHEET=
   NOCODB_SHIFTS_SHEET=
   NOCODB_SHIFT_SIGNUPS_SHEET=

   # Domain Configuration
   DOMAIN=cmlite.org

   # MkDocs Integration
   MKDOCS_URL=https://cmlite.org
   MKDOCS_SEARCH_URL=https://cmlite.org
   MKDOCS_SITE_SERVER_PORT=4002

   # Server Configuration
   PORT=3000
   NODE_ENV=production

   # Session Secret (Generate with: openssl rand -hex 32)
   SESSION_SECRET=your-secure-random-string

   # Map Defaults (Edmonton, Alberta, Canada)
   DEFAULT_LAT=53.5461
   DEFAULT_LNG=-113.4938
   DEFAULT_ZOOM=11

   # Optional: Map Boundaries (prevents users from adding points outside area)
   # BOUND_NORTH=53.7
   # BOUND_SOUTH=53.4
   # BOUND_EAST=-113.3
   # BOUND_WEST=-113.7

   # Cloudflare Settings
   TRUST_PROXY=true
   COOKIE_DOMAIN=.cmlite.org

   # Allowed Origins
   ALLOWED_ORIGINS=https://map.cmlite.org,http://localhost:3000

   # Email Configuration (Required for full functionality)
   # Used for password recovery, shift notifications, and admin broadcast emails
   SMTP_HOST=smtp.gmail.com
   SMTP_PORT=587
   SMTP_SECURE=false
   SMTP_USER=your-email@gmail.com
   SMTP_PASS=your-app-password
   EMAIL_FROM_NAME=CMlite Support
   EMAIL_FROM_ADDRESS=noreply@cmlite.org
   APP_NAME=CMlite Map

   # Listmonk Integration (Optional - enhances email marketing capabilities)
   LISTMONK_URL=http://localhost:9000
   LISTMONK_USERNAME=admin
   LISTMONK_PASSWORD=your-listmonk-password
   LISTMONK_ENABLED=true
   LISTMONK_SYNC_ON_STARTUP=true
   LISTMONK_AUTO_CREATE_LISTS=true
   ```

3. **Auto-Create Database Structure**

   Run the build script to create required tables:
   ```bash
   chmod +x build-nocodb.sh
   ./build-nocodb.sh
   ```

   **For migrating from an existing NocoDB base:**
   ```bash
   ./build-nocodb.sh --migrate-data
   ```

   This creates six tables:
   - **Locations** - Main map data with geo-location, contact info, support levels
   - **Login** - User authentication (email, name, admin flag)
   - **Settings** - Admin configuration and QR codes
   - **Shifts** - Shift scheduling and management
   - **Shift Signups** - User shift registrations
   - **Cuts** - Geographic polygon overlays for map regions

   ### Data Migration Options

   The build script supports data migration from existing NocoDB bases:

   **Interactive Mode (Default):**
   ```bash
   ./build-nocodb.sh
   ```
   - Prompts you to choose between fresh installation or data migration
   - Automatically detects current base from .env file
   - Provides guided setup with clear options

   **Fresh Installation:**
   - Creates new base with sample data
   - Sets up default admin user (admin@thebunkerops.ca / admin123)
   - Configures default settings

   **Migration from Existing Base:**
   ```bash
   ./build-nocodb.sh --migrate-data  # Skip prompt, go direct to migration
   ```
   - Lists all available bases in your NocoDB instance
   - Highlights current base from .env file for easy selection
   - Allows you to select source base for migration
   - Choose specific tables to migrate (locations, login, settings, etc.)
   - Filters out auto-generated columns to prevent conflicts
   - Preserves your existing data while updating to new schema
   - Original base remains unchanged as backup

   **Migration Process:**
   1. Script displays available bases with IDs and descriptions
   2. Select source base by entering the corresponding number
   3. Choose tables to migrate (comma-separated numbers or 'all')
   4. Data is exported from source and imported to new base
   5. .env file automatically updated with new URLs

   **Important Migration Notes:**
   - ✅ Original data remains untouched (creates new base)
   - ✅ Auto-generates new IDs to prevent conflicts
   - ✅ Validates table structure compatibility
   - ⚠️ Review migrated data before using in production
   - ⚠️ Existing admin passwords may need to be reset

4. **Get Table URLs**

   After the script completes:
   1. Login to your NocoDB instance at https://db.cmlite.org
   2. Navigate to your project ("Map Viewer Project - TIMESTAMP")
   3. Copy the view URLs for each table from your browser address bar
   4. URLs should look like: `https://db.cmlite.org/dashboard/#/nc/project-id/table-id`

5. **Update Environment with URLs**

   Edit your `.env` file and add the table URLs:
   ```env
   NOCODB_VIEW_URL=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/m6g7bkzv7s1w2ur
   NOCODB_LOGIN_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mizyc64e4r7ppzh
   NOCODB_SETTINGS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mix06f2mlep7gqb
   NOCODB_SHIFTS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mkx0tex0iquus1u
   NOCODB_SHIFT_SIGNUPS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mi8jg1tn26mu8fj
   NOCODB_CUTS_SHEET=https://db.cmlite.org/dashboard/#/nc/pnsalzrup2zqvz8/mxxxxxxxxxxxxxx
   ```

6. **Build and Deploy**

   Build the Docker image and start the application:
   ```bash
   # Build the Docker image
   docker-compose build

   # Start the application
   docker-compose up -d
   ```

7. **Verify Installation**

   - Check container status: `docker-compose ps`
   - View logs: `docker-compose logs -f map-viewer`
   - Access the application at: http://localhost:3000
   - Access shift management at: http://localhost:3000/shifts.html
   - Access admin panel at: http://localhost:3000/admin.html (admin users only)

## Database Schema

The build script automatically creates the following table structure:

### Main Locations Table
- `ID` (ID): Auto-incrementing primary key
- `Geo-Location` (GeoData): Geographic coordinate data 
- `latitude` (Decimal): Precision 8, Scale 8
- `longitude` (Decimal): Precision 8, Scale 8
- `First Name` (Single Line Text): Person's first name
- `Last Name` (Single Line Text): Person's last name
- `Email` (Email): Email address
- `Phone` (PhoneNumber): Phone number with validation
- `Unit Number` (Single Line Text): Unit or apartment number
- `Support Level` (Single Select): Options: "1" (Green), "2" (Yellow), "3" (Orange), "4" (Red)
- `Address` (Single Line Text): Street address
- `Sign` (Checkbox): Has campaign sign
- `Sign Size` (Single Select): Options: "Regular" (Blue), "Large" (Green), "Unsure" (Orange)
- `Notes` (Long Text): Additional details and comments
- `created_by_user` (Single Line Text): Creator email
- `last_updated_by_user` (Single Line Text): Last updater email

### Login Table
- `ID` (ID): Auto-incrementing primary key
- `Email` (Email): User email address (required)
- `Password` (Single Line Text): User password (required)
- `Name` (Single Line Text): User display name  
- `Admin` (Checkbox): Admin privileges
- `UserType` or `User Type` (Single Select): Options: "user" (Blue), "temp" (Orange) - User role type
- `ExpiresAt` (DateTime): Expiration date for temporary users
- `ExpireDays` (Number): Number of days until temp user expires
- `Created At` (DateTime): Account creation timestamp
- `Last Login` (DateTime): Last login timestamp

### Settings Table
- `ID` (ID): Auto-incrementing primary key
- `created_at` (DateTime): Record creation timestamp
- `created_by` (Single Line Text): Creator identifier
- `Geo-Location` (Single Line Text): Format "latitude;longitude"
- `latitude` (Decimal): Precision 8, Scale 8
- `longitude` (Decimal): Precision 8, Scale 8
- `zoom` (Number): Map zoom level
- `Walk Sheet Title` (Single Line Text): Title for walk sheets
- `Walk Sheet Subtitle` (Single Line Text): Subtitle for walk sheets
- `Walk Sheet Footer` (Long Text): Footer text for walk sheets
- `QR Code 1 URL` (URL): First QR code link
- `QR Code 1 Label` (Single Line Text): First QR code label
- `QR Code 2 URL` (URL): Second QR code link
- `QR Code 2 Label` (Single Line Text): Second QR code label
- `QR Code 3 URL` (URL): Third QR code link
- `QR Code 3 Label` (Single Line Text): Third QR code label

### Shifts Table
- `ID` (ID): Auto-incrementing primary key
- `Title` (Single Line Text): Shift title (required)
- `Description` (Long Text): Detailed shift description
- `Date` (Date): Shift date (required)
- `Start Time` (Time): Shift start time (required)
- `End Time` (Time): Shift end time (required)
- `Location` (Single Line Text): Shift location
- `Max Volunteers` (Number): Maximum volunteer capacity (required)
- `Current Volunteers` (Number): Current volunteer count
- `Status` (Single Select): Options: "Open" (Green), "Full" (Orange), "Cancelled" (Red)
- `Created By` (Single Line Text): Creator identifier
- `Created At` (DateTime): Creation timestamp
- `Updated At` (DateTime): Last update timestamp

### Shift Signups Table  
- `ID` (ID): Auto-incrementing primary key
- `Shift ID` (Number): Reference to shifts table (required)
- `Shift Title` (Single Line Text): Copy of shift title for reference
- `User Email` (Email): User's email address (required)
- `User Name` (Single Line Text): User's display name
- `Signup Date` (DateTime): When user signed up
- `Status` (Single Select): Options: "Confirmed" (Green), "Cancelled" (Red)

### Cuts Table
- `ID` (ID): Auto-incrementing primary key
- `name` (Single Line Text): Cut name/title (required)
- `description` (Long Text): Detailed description of the cut
- `geojson` (Long Text): GeoJSON polygon data (required)
- `bounds_north` (Decimal): Northern boundary latitude (Precision 8, Scale 8)
- `bounds_south` (Decimal): Southern boundary latitude (Precision 8, Scale 8)
- `bounds_east` (Decimal): Eastern boundary longitude (Precision 8, Scale 8)
- `bounds_west` (Decimal): Western boundary longitude (Precision 8, Scale 8)
- `color` (Single Line Text): Hex color code (default: "#007bff")
- `opacity` (Decimal): Fill opacity 0-1 (Precision 3, Scale 2, default: 0.3)
- `category` (Single Line Text): Category/tag for organization
- `is_public` (Checkbox): Whether cut is visible to non-admin users (default: true)
- `created_by` (Single Line Text): Creator email
- `created_at` (DateTime): Creation timestamp
- `updated_at` (DateTime): Last update timestamp

## Enhanced Geocoding Features

The application includes a robust, multi-provider geocoding system designed for high accuracy and reliability in address processing.

### 🌍 Multi-Provider Geocoding System

- **Premium Providers**: Mapbox and LocationIQ for highest accuracy
- **Free Providers**: Nominatim (OpenStreetMap), Photon, and ArcGIS
- **Automatic Fallback**: If premium providers fail, automatically tries free alternatives
- **Provider Selection**: Intelligent provider selection based on availability and API keys
- **Rate Limiting**: Built-in delays to respect API rate limits

### 🎯 Geocoding Quality Assessment

- **Confidence Scoring**: Every geocoded address receives a confidence score (0-100%)
- **Address Validation**: Detects potentially malformed or problematic addresses
- **Quality Warnings**: Identifies addresses that may need manual review
- **Provider-Specific Scoring**: Different confidence algorithms per provider
- **Combined Confidence**: Unified scoring system across all providers

### 📊 CSV Data Import with Enhanced Processing

- **Batch Geocoding**: Process hundreds of addresses with real-time progress tracking
- **Unit Number Support**: Automatically handles apartment/unit numbers in addresses
- **Visual Progress**: Live progress bars and status updates during processing
- **Error Handling**: Comprehensive error tracking and reporting
- **Retry Logic**: Automatic retry for failed addresses with different providers
- **Downloadable Reports**: Detailed CSV reports with all results and recommendations

### 🔍 Database Scan and Geocode

Admin-only feature to scan existing database records and geocode missing location data:

- **Smart Scanning**: Identifies records missing geo-location data
- **Batch Processing**: Processes all missing records with progress tracking
- **Real-time Updates**: Updates database records directly with coordinates
- **Confidence Tracking**: Saves confidence scores and provider information
- **Comprehensive Reports**: Generates detailed reports of all geocoding activities
- **Safety Features**: Rate limiting and error handling to protect APIs

### 📈 Geocoding Reports and Analytics

- **Success Rate Tracking**: Monitor geocoding success rates over time
- **Provider Performance**: Compare performance across different geocoding providers
- **Quality Analysis**: Identify patterns in low-confidence or failed addresses
- **CSV Export**: Export all geocoding results for external analysis
- **Recommendations**: Automated suggestions for improving address quality
- **Error Categorization**: Detailed breakdown of geocoding failures

### ⚙️ Geocoding Configuration

Add these optional environment variables for enhanced geocoding:

```env
# Premium Geocoding Providers (Recommended)
MAPBOX_ACCESS_TOKEN=pk.your-mapbox-token-here
LOCATIONIQ_API_KEY=your-locationiq-key-here
```

**Benefits of Premium Providers:**
- Higher accuracy for Canadian addresses
- Better handling of complex addresses
- More reliable service uptime
- Enhanced address normalization
- Detailed confidence scoring

**Free Provider Fallback:**
- Automatic fallback if premium providers fail
- No additional cost for basic geocoding needs
- Suitable for non-critical applications
- OpenStreetMap-based accuracy

### 🛠️ Admin Geocoding Tools

Administrators have access to powerful geocoding management tools:

- **Provider Status Dashboard**: View availability of all geocoding providers
- **Batch Operations**: Process multiple addresses simultaneously
- **Quality Control**: Review and approve low-confidence geocoding results
- **Database Maintenance**: Scan and update existing records with missing coordinates
- **Performance Monitoring**: Track geocoding success rates and provider performance
- **Cost Management**: Monitor API usage for premium providers

## Email Features

The system includes comprehensive email functionality powered by SMTP configuration:

### 🔧 Admin Email Broadcasting
- **Rich HTML email composer** with live preview and formatting toolbar
- **Mass email sending** to all registered users
- **Professional email templates** with consistent branding
- **Real-time recipient counting** and success/failure tracking
- **Visual progress tracking** with animated progress bars and individual email status
- **Detailed delivery reports** showing successful sends and failure reasons
- Support for rich text content including headers, lists, links, and formatting

### 📅 Shift Email Notifications  
- **Automated shift detail emails** sent to all volunteers
- **Professional HTML templates** with complete shift information
- **Shift status tracking** (open, full, cancelled) in emails
- **Volunteer management** - add/remove users from shifts
- **Calendar integration** - Google, Outlook, and Apple calendar export
- **Visual progress indicators** with real-time sending status per volunteer
- **Email status reporting** with success/failure details and error messages

### 👤 User Account Emails
- **Login credential delivery** for new users
- **Password recovery** with secure email notifications
- **Temporary user accounts** with automatic expiration tracking
- **Professional HTML and plain text** email templates

### 📧 Email Template System
- **Responsive HTML templates** with professional design
- **Variable substitution** for personalized content
- **Multi-format support** (HTML and plain text)
- **Consistent branding** across all email communications

## Listmonk Integration

The application includes real-time integration with [Listmonk](https://listmonk.app/), a self-hosted newsletter and mailing list manager, enabling advanced email marketing capabilities and subscriber management.

### 🔄 Real-Time Synchronization

The system automatically synchronizes data between the Map application and Listmonk:

- **Automatic List Creation**: Creates and maintains email lists for different user segments
- **Real-Time Updates**: New locations and users are instantly synced to Listmonk
- **Bi-Directional Sync**: Unsubscribes in Listmonk update the Map database
- **Error Handling**: Visual status indicators and detailed logging for sync failures

### 📋 Automated List Management

The integration automatically manages the following Listmonk subscriber lists:

- **All Locations**: Complete list of all mapped locations with contact information
- **All Users**: List of all registered Map application users
- **Support Level Lists**: Separate lists for each support level (1-4) for targeted campaigns
- **Sign Status Lists**: Lists based on campaign sign status (Has Sign, No Sign)
- **Combined Lists**: Smart combinations like "Support Level 4 with Signs" for precision targeting

### ⚙️ Configuration

Add the following environment variables to your `.env` file:

```env
# Listmonk Integration (Optional - enhances email marketing capabilities)
LISTMONK_API_URL=http://172.20.0.9:9000/api
LISTMONK_USERNAME=admin
LISTMONK_PASSWORD=your-listmonk-password
LISTMONK_SYNC_ENABLED=true

# Listmonk Sync Settings
LISTMONK_INITIAL_SYNC=true  # Set to true only for first run to sync existing data
```

### 🔍 Finding the Correct Listmonk API URL

The `LISTMONK_API_URL` must point to the internal Docker network address where Listmonk is running. Here are several methods to find the correct URL:

#### Method 1: Using Docker Inspect (Recommended)

If Listmonk is running in a Docker container, find its internal IP address:

```bash
# List all running containers
docker ps

# Find the Listmonk container name/ID, then inspect it
docker inspect <listmonk-container-name> | grep IPAddress

# Example output:
# "IPAddress": "172.20.0.9"
```

Your `LISTMONK_API_URL` would then be: `http://172.20.0.9:9000/api`

#### Method 2: Using Docker Network Inspection

If both containers are on the same Docker network:

```bash
# List Docker networks
docker network ls

# Inspect the network (usually named after your docker-compose project)
docker network inspect <network-name>

# Look for the Listmonk container in the "Containers" section
# Note the "IPv4Address" value
```

#### Method 3: Using Container Names (Docker Compose)

If using Docker Compose with both services in the same `docker-compose.yml`:

```yaml
# In your docker-compose.yml
services:
  listmonk:
    image: listmonk/listmonk:latest
    container_name: listmonk
    # ... other config

  map-app:
    # ... your map application config
```

You can use the service name: `LISTMONK_API_URL=http://listmonk:9000/api`

#### Method 4: Check Docker Compose Logs

```bash
# View Listmonk container logs to see what IP it's binding to
docker-compose logs listmonk

# Look for lines like:
# listmonk_1  | INFO[0000] listmonk started. IP: 0.0.0.0:9000
```

#### Method 5: Testing Connectivity

Test if your URL is correct by running a test from within your Map application container:

```bash
# Access your map application container
docker exec -it <map-container-name> /bin/bash

# Test connectivity to Listmonk
curl http://172.20.0.9:9000/api/health
# Should return: {"data":true}

# Or test with your credentials
curl -u "admin:your-password" http://172.20.0.9:9000/api/lists
```

#### Common IP Ranges

Docker typically assigns containers to these network ranges:
- `172.17.0.x` - Default bridge network
- `172.18.0.x` - Custom bridge networks
- `172.20.0.x` - Docker Compose networks
- `192.168.x.x` - Some custom networks

#### Troubleshooting Connection Issues

If you're having connection problems:

1. **Verify Listmonk is running**: `docker ps | grep listmonk`
2. **Check port exposure**: Ensure Listmonk exposes port 9000
3. **Network connectivity**: Both containers must be on the same Docker network
4. **Firewall rules**: Ensure no firewalls block inter-container communication
5. **DNS resolution**: Try IP address instead of container name if DNS fails

#### Example Working Configuration

```env
# Working example from a real deployment
LISTMONK_API_URL=http://172.20.0.9:9000/api
LISTMONK_USERNAME=API
LISTMONK_PASSWORD=s0f6qSuWTGMX8AWbz8f4EQxGFSZCZxAC
LISTMONK_SYNC_ENABLED=true
LISTMONK_INITIAL_SYNC=true
```

> **Note**: Never use `localhost` or `127.0.0.1` for the Listmonk URL when running in Docker containers, as this refers to the container's own loopback interface, not the Listmonk container.

### 📊 Admin Features

Administrators have access to comprehensive Listmonk management tools:

#### Real-Time Status Monitoring
- **Connection Status**: Live indicator showing Listmonk connectivity
- **Sync Statistics**: Real-time counts of subscribers, lists, and sync operations
- **Error Notifications**: Popup alerts and terminal logs for sync failures
- **Last Sync Timestamps**: Track when data was last synchronized

#### Bulk Operations
- **Full Resync**: Manually trigger complete data synchronization
- **Selective Sync**: Sync specific data types (locations, users, lists)
- **Progress Tracking**: Visual progress bars for bulk operations
- **Detailed Reports**: Success/failure counts with error details

#### List Management
- **Auto-List Creation**: Automatically create and maintain subscriber lists
- **Custom Segmentation**: Create lists based on support levels, sign status, and combinations
- **Subscriber Counts**: Real-time subscriber counts for each list
- **List Status Monitoring**: Track list health and sync status

### 🔌 API Integration Points

The Listmonk integration adds the following API endpoints:

#### Admin Listmonk Endpoints (requires admin privileges)
- `GET /api/listmonk/status` - Get connection status and sync statistics
- `POST /api/listmonk/sync/full` - Trigger full synchronization
- `POST /api/listmonk/sync/locations` - Sync locations only
- `POST /api/listmonk/sync/users` - Sync users only
- `POST /api/listmonk/test-connection` - Test Listmonk connectivity
- `POST /api/listmonk/reinitialize` - Recreate all lists and resync data
- `GET /api/listmonk/lists` - Get all Listmonk lists with subscriber counts

### 🚀 Getting Started with Listmonk

1. **Set up Listmonk**: Deploy Listmonk using Docker Compose (see parent project documentation)
2. **Configure Integration**: Add Listmonk credentials to your `.env` file
3. **Initialize Lists**: Lists are automatically created on first startup
4. **Monitor Status**: Check the admin panel for sync status and connection health
5. **Customize Campaigns**: Use Listmonk's web interface to create targeted email campaigns

### 🔍 Status Indicators

The system provides visual feedback on integration status:

- **🟢 Connected**: Listmonk is accessible and syncing properly
- **🟡 Warning**: Sync delays or minor issues detected
- **🔴 Error**: Connection failed or sync errors occurred
- **⚪ Disabled**: Listmonk integration is disabled

### 📈 Benefits

- **Enhanced Email Marketing**: Leverage Listmonk's advanced campaign features
- **Automated Segmentation**: Automatic subscriber lists based on Map data
- **Improved Deliverability**: Professional email marketing infrastructure
- **Real-Time Updates**: Always-current subscriber information
- **Detailed Analytics**: Track email engagement and campaign performance
- **Professional Templates**: Rich HTML email templates and campaign builder

### 🔧 Troubleshooting

Common issues and solutions:

- **Connection Failed**: Verify Listmonk URL and credentials in `.env`
- **Sync Errors**: Check terminal logs for detailed error messages
- **Missing Lists**: Enable `LISTMONK_AUTO_CREATE_LISTS=true` and restart
- **Slow Sync**: Monitor network connectivity and Listmonk performance
- **Duplicate Subscribers**: The system automatically handles duplicates using email addresses

## Public Volunteer Signup

The application includes a public-facing volunteer signup system that allows visitors to view and sign up for volunteer opportunities without requiring an account. This feature is perfect for sharing volunteer opportunities via social media, QR codes, or direct links.

### 🌐 Public Shift Viewing

- **No Authentication Required**: Visitors can browse all public volunteer opportunities at `/public-shifts.html`
- **Responsive Design**: Mobile-optimized interface for easy viewing on all devices
- **Shift Filtering**: Filter opportunities by date to find relevant events
- **Direct Linking**: Share specific shifts using unique URLs (e.g., `#shift-123`)

### 👤 Automatic Account Creation

- **Temporary Accounts**: New volunteers automatically receive temporary accounts during signup
- **Account Credentials**: Login details sent via professional HTML email
- **Shift-Based Expiration**: Accounts expire automatically after the volunteer shift
- **Seamless Transition**: Temp users can access the main application to manage their signups

### 📧 Professional Email Confirmations

- **Instant Notifications**: Confirmation emails sent immediately after signup
- **Rich HTML Templates**: Professional, responsive email design
- **Shift Details**: Complete shift information including date, time, location
- **Login Instructions**: Clear instructions for accessing the volunteer account
- **Branded Experience**: Consistent branding with organization identity

### 🔗 Admin Share Controls

- **Public/Private Toggle**: Admins control which shifts appear on the public page
- **Shareable Links**: Generate and copy direct links to volunteer opportunities
- **QR Code Ready**: Links work perfectly in QR codes for physical materials
- **Real-time Updates**: Changes to shift visibility reflect immediately

### 🛡️ Security & Abuse Prevention

- **Rate Limiting**: Built-in protection against spam signups (5 signups per 15 minutes per IP)
- **Email Validation**: Automatic validation of email addresses during signup
- **Duplicate Prevention**: System prevents multiple signups for the same shift
- **Admin Oversight**: Admins can view and manage all public signups

### 📱 Mobile-First Design

- **Touch-Friendly**: Optimized for mobile signup on phones and tablets
- **Fast Loading**: Lightweight design for quick loading on all connections
- **Accessible**: Screen reader compatible and keyboard navigable
- **Progressive Enhancement**: Works without JavaScript for maximum compatibility

### 🚀 Integration Features

- **Existing User Support**: Returning volunteers use their existing accounts
- **Signup Tracking**: Public signups marked separately for reporting
- **Volunteer Management**: Public signups integrate seamlessly with admin tools
- **Email Templates**: Separate templates for new vs existing users

Access the public volunteer signup page at: **`/public-shifts.html`**

## API Endpoints

### Public Shift Endpoints (No Authentication Required)

| Endpoint | Method | Description | Rate Limit |
|----------|--------|-------------|------------|
| `/public/shifts` | GET | Get all public shifts with locations | None |
| `/public/shifts/signup` | POST | Sign up for a public shift | 5 per 15 min per IP |

**Public Shift Signup Request Body:**
```json
{
  "shift_id": "integer",
  "first_name": "string",
  "last_name": "string", 
  "email": "string",
  "phone": "string (optional)"
}
```

### Public Endpoints (Location & Health)

- `GET /api/locations` - Fetch all locations (requires auth)
- `POST /api/locations` - Create new location (requires auth)
- `GET /api/locations/:id` - Get single location (requires auth)
- `PUT /api/locations/:id` - Update location (requires auth)
- `DELETE /api/locations/:id` - Delete location (requires auth)
- `GET /api/config/start-location` - Get map start location
- `GET /health` - Health check

### Shifts Endpoints (requires authentication)

- `GET /api/shifts` - Get all available shifts
- `GET /api/shifts/my-signups` - Get current user's shift signups
- `POST /api/shifts/:shiftId/signup` - Sign up for a shift
- `POST /api/shifts/:shiftId/cancel` - Cancel shift signup

### Shifts Admin Endpoints (requires admin privileges)

- `GET /api/shifts/admin` - Get all shifts including cancelled ones
- `POST /api/shifts/admin` - Create new shift
- `PUT /api/shifts/admin/:id` - Update existing shift
- `DELETE /api/shifts/admin/:id` - Delete shift
- `POST /api/shifts/admin/:shiftId/add-user` - Add user to shift
- `DELETE /api/shifts/admin/:shiftId/remove-user/:userId` - Remove user from shift
- `POST /api/shifts/admin/:shiftId/email-details` - Email shift details to all volunteers

### Authentication Endpoints

- `POST /api/auth/login` - User login
- `GET /api/auth/check` - Check authentication status
- `POST /api/auth/logout` - User logout

### Admin Endpoints (requires admin privileges)

- `GET /api/admin/start-location` - Get start location with source info
- `POST /api/admin/start-location` - Update map start location
- `GET /api/admin/walk-sheet-config` - Get walk sheet configuration
- `POST /api/admin/walk-sheet-config` - Save walk sheet configuration

### User Management Endpoints (requires admin privileges)

- `GET /api/users` - Get all users
- `POST /api/users` - Create new user
- `DELETE /api/users/:id` - Delete user
- `POST /api/users/:id/send-login-details` - Send login details to user
- `POST /api/users/email-all` - Send broadcast email to all users

### Cuts Endpoints

#### Public Cuts Endpoints (requires authentication)
- `GET /api/cuts/public` - Get all public cuts visible to users

#### Admin Cuts Endpoints (requires admin privileges)
- `GET /api/cuts` - Get all cuts (including private ones)
- `POST /api/cuts` - Create new cut
- `GET /api/cuts/:id` - Get single cut by ID
- `PUT /api/cuts/:id` - Update existing cut
- `DELETE /api/cuts/:id` - Delete cut

### Geocoding Endpoints (requires authentication)

- `GET /api/geocode/reverse?lat=<lat>&lng=<lng>` - Reverse geocode coordinates to address
- `GET /api/geocode/forward?address=<address>` - Forward geocode address to coordinates  
- `GET /api/geocode/search?query=<query>&limit=<number>` - Search for multiple address matches
- `GET /api/geocode/cache/stats` - Get geocoding cache statistics (admin only)

All geocoding endpoints include rate limiting (30 requests per 15 minutes per IP) and support Cloudflare IP detection for accurate rate limiting.

## Shifts Management

The application includes a comprehensive volunteer shift management system accessible at `/shifts.html`.

### User Features

- **Dual View Options**: Toggle between grid view and calendar view for shift display
- **Calendar View**: Interactive monthly calendar showing shifts with color-coded indicators:
  - Green: Shifts you've signed up for
  - Blue: Available shifts you can join
  - Gray: Full shifts (no spots available)
- **View Available Shifts**: See all upcoming shifts with date, time, and capacity information
- **Sign Up for Shifts**: One-click signup for available shifts (works in both views)
- **My Shifts Dashboard**: View all your current shift signups at the top of the page
- **Cancel Signups**: Cancel your shift signups when needed
- **Date Filtering**: Filter shifts by specific dates (applies to both views)
- **Real-time Updates**: Shift availability updates dynamically
- **Interactive Calendar**: Click on calendar shifts for detailed popup with signup options
- **Calendar Navigation**: Navigate between months to view future shifts

### Admin Features

Administrators have additional capabilities for managing shifts:

- **Create New Shifts**: Add new volunteer shifts with date, time, location, and capacity
- **Edit Existing Shifts**: Modify shift details, times, or capacity
- **Cancel Shifts**: Mark shifts as cancelled (they remain in system but hidden from users)
- **View All Signups**: See who has signed up for each shift
- **Manage Capacity**: Set maximum number of volunteers per shift
- **Email Notifications**: Send shift details to all volunteers via email

### Shift Status System

- **Open** (Green): Shift is available and accepting signups
- **Full** (Orange): Shift has reached maximum capacity  
- **Cancelled** (Red): Shift has been cancelled by admin

The system automatically updates shift status based on current signups vs. maximum capacity.

## Cut Feature - Geographic Overlays

The Cut feature allows administrators to create and manage polygon overlays on the map, useful for defining geographic regions, neighborhoods, or operational areas.

### Admin Cut Creation

Administrators can create cuts through the admin panel at `/admin.html`:

- **Interactive Drawing**: Click points on the map to define polygon boundaries
- **Real-time Preview**: See the polygon shape as you draw
- **Point Management**: Add points by clicking, finish by clicking the first point or using the complete button
- **Visual Feedback**: Clear indicators for drawing mode and vertex points

### Cut Properties

Each cut supports the following properties:

- **Name**: Required title for the cut (e.g., "Downtown District", "Canvassing Area A")
- **Description**: Optional detailed description of the cut's purpose
- **Color**: Hex color code for the polygon border and fill (default: "#007bff")
- **Opacity**: Fill transparency from 0.0 (transparent) to 1.0 (opaque) (default: 0.3)
- **Category**: Optional categorization tag for organization
- **Visibility**: Public (visible to all users) or Private (admin-only)

### Cut Management

- **View All Cuts**: List all existing cuts with their properties
- **Edit Cuts**: Modify any cut property after creation
- **Delete Cuts**: Remove cuts with confirmation prompts
- **Import/Export**: JSON format for backup and migration
- **Real-time Updates**: Changes appear immediately on all connected maps

### Public Cut Display

Public cuts are automatically displayed on the main map for all authenticated users:

- **Polygon Overlays**: Cuts appear as colored polygon overlays
- **Non-Interactive**: Users can see cuts but cannot modify them
- **Responsive**: Cuts adapt to different screen sizes and zoom levels
- **Performance Optimized**: Efficient rendering for multiple cuts

### Use Cases

- **Canvassing Districts**: Define geographic areas for volunteer assignments
- **Neighborhood Boundaries**: Mark community or administrative boundaries
- **Event Areas**: Highlight locations for rallies, meetings, or activities
- **Restricted Zones**: Mark areas requiring special attention or restrictions
- **Progress Tracking**: Visual representation of completed campaign areas

## Unified Search System

The application features a powerful unified search system accessible via the search bar in the header or by pressing `Ctrl+K` anywhere in the application.

### Search Modes

The search system operates in two modes:

1. **Documentation Search**: Search through integrated MkDocs documentation
2. **Address Search**: Search for addresses and geographic locations
3. **Database Search**: Search through loaded location records on the map

### Features

- **Mode Toggle**: Switch between docs, address, and database search with dedicated buttons
- **Keyboard Shortcuts**: 
  - `Ctrl+K` or `Cmd+K`: Focus search input from anywhere
  - `Escape`: Close search results
  - Arrow keys: Navigate through search results
  - `Enter`: Select highlighted result
- **Real-time Results**: Search results update as you type (minimum 2 characters)
- **Smart Caching**: Results are cached for improved performance
- **QR Code Generation**: Generate QR codes for documentation links
- **Visual Feedback**: Loading states, result counts, and error handling

### Documentation Search

When connected to a MkDocs documentation site:
- **Full-text Search**: Search through all documentation content
- **Snippet Preview**: See relevant excerpts with search terms highlighted
- **Direct Navigation**: Click results to open documentation pages
- **Path Display**: Shows the document path and section
- **QR Code Support**: Generate QR codes for sharing documentation links

### Address Search  

For geographic location search:
- **Multi-Provider Geocoding**: Uses multiple geocoding providers for maximum accuracy
- **Mapbox Integration**: Premium provider with structured address input (when API key provided)
- **Fallback Providers**: Free providers (Nominatim, Photon, ArcGIS, LocationIQ) for comprehensive coverage
- **Multiple Results**: Returns up to 5 address matches
- **Map Integration**: Click results to view location on map
- **Temporary Markers**: Visual markers for search results
- **Quick Actions**: Add locations directly from search results
- **Coordinate Display**: Shows precise latitude/longitude coordinates

#### Geocoding Configuration

For improved geocoding accuracy, you can configure premium providers:

```env
# Mapbox API Key (Recommended for best accuracy)
MAPBOX_ACCESS_TOKEN=your_mapbox_access_token_here

# LocationIQ API Key (Alternative premium option)
LOCATIONIQ_API_KEY=your_locationiq_api_key_here
```

**Mapbox Setup:**
1. Sign up at [mapbox.com](https://www.mapbox.com/)
2. Get your access token from the dashboard
3. Add `MAPBOX_ACCESS_TOKEN=your_token_here` to your `.env` file
4. Restart the application

When Mapbox is configured, it will be used as the primary geocoding provider with automatic fallback to free providers if needed.

### Database Search
For searching through loaded location data:
- **Full-text Search**: Search through names, addresses, emails, phone numbers, and notes
- **Smart Matching**: Finds partial matches across multiple fields
- **Result Preview**: See relevant details with search terms highlighted
- **Map Integration**: Click results to pan to location and open marker popup

### Configuration

The unified search system integrates with MkDocs documentation when configured:

```env
MKDOCS_URL=https://your-docs-site.com
MKDOCS_SEARCH_URL=https://your-docs-site.com
MKDOCS_SITE_SERVER_PORT=4002
```

### Rate Limiting

Address search is rate-limited to prevent abuse:
- 30 requests per 15-minute window per IP
- Cloudflare IP detection for accurate limiting
- Graceful error handling for rate limit exceeded

## Admin Panel

Users with admin privileges can access the admin panel at `/admin.html` to configure system settings.

### Features

#### Dashboard Analytics

- **Campaign Overview**: Real-time statistics and metrics
- **Support Distribution**: Visual breakdown of support levels (1-4)
- **Sign Tracking**: Monitor lawn sign requests
- **User Analytics**: Track user growth and daily entries
- **Performance Score**: Overall campaign performance metric

#### Start Location Configuration

- **Interactive Map**: Visual interface for selecting coordinates
- **Real-time Preview**: See changes immediately on the admin map
- **Validation**: Built-in coordinate and zoom level validation

#### Walk Sheet Generator

- **Printable Forms**: Generate 8.5x11 walk sheets for door-to-door canvassing
- **QR Code Integration**: Add up to 3 QR codes with custom URLs and labels
- **Form Field Matching**: Automatically matches fields from the main location form
- **Live Preview**: See changes as you type
- **Print Optimization**: Proper formatting for printing or PDF export
- **Persistent Storage**: All QR codes and settings saved to NocoDB

#### Shift Management

- **Create Shifts**: Set up volunteer shifts with dates, times, and capacity
- **Manage Volunteers**: View signups and manage shift participants
- **Real-time Updates**: See shift status changes immediately

#### User Management

- **Create Users**: Add new user accounts with email and password
- **Role Assignment**: Assign admin or user privileges
- **User List**: View all registered users with their details and creation dates
- **Delete Users**: Remove user accounts (with confirmation prompts)
- **Security**: Password validation and admin-only access

#### Cut Management

- **Interactive Drawing**: Click-to-add-points polygon drawing system on the map
- **Cut Properties**: Configure name, description, color, opacity, and category
- **Visibility Control**: Set cuts as public (visible to all users) or private (admin-only)
- **Real-time Preview**: See cut polygons rendered on the map during creation
- **Cut Management**: View, edit, and delete existing cuts with full CRUD operations
- **Import/Export**: JSON import/export functionality for cut data backup and migration
- **Map Integration**: Cuts display as colored polygon overlays on both admin and public maps
- **Responsive Design**: Touch-friendly interface for mobile and tablet devices

#### Convert Data

- **CSV Upload**: Upload CSV files containing addresses for bulk import
- **Drag & Drop Interface**: Easy file upload with visual feedback
- **Real-time Geocoding**: Addresses are geocoded in real-time with progress tracking
- **Visual Progress**: Live progress bar and status updates during processing
- **Map Preview**: Interactive map showing geocoded locations before saving
- **Results Table**: Detailed table with success/error status for each address
- **Batch Save**: Save all successfully geocoded locations to the database
- **Field Mapping**: Automatically maps common CSV fields (First Name, Last Name, Email, Phone, etc.)
- **Error Handling**: Clear error messages for failed geocoding attempts
- **File Validation**: CSV format validation and file size limits (10MB max)

### Access Control

- Admin access is controlled via the `Admin` checkbox in the Login table
- Only authenticated users with admin privileges can access `/admin.html`
- Admin status is checked on every request to admin endpoints
- User management functions are restricted to admin users only

### Start Location Priority

The system uses a cascading fallback system for map start location:
1. **Database**: Admin-configured location stored in Settings table (highest priority)
2. **Environment**: Default values from .env file (medium priority)  
3. **Hardcoded**: Edmonton, Canada coordinates (lowest priority)

## Configuration

All configuration is done via environment variables:

| Variable | Description | Default |
|----------|-------------|---------|
| `NOCODB_API_URL` | NocoDB API base URL | Required |
| `NOCODB_API_TOKEN` | API authentication token | Required |
| `NOCODB_VIEW_URL` | Full NocoDB view URL for locations table | Required |
| `NOCODB_LOGIN_SHEET` | Login table URL for authentication | Required |
| `NOCODB_SETTINGS_SHEET` | Settings table URL for admin config | Required |
| `NOCODB_SHIFTS_SHEET` | Shifts table URL for shift management | Required |
| `NOCODB_SHIFT_SIGNUPS_SHEET` | Shift signups table URL for user registrations | Required |
| `DOMAIN` | Primary domain for the application | Required |
| `MKDOCS_URL` | MkDocs documentation site URL | Optional |
| `MKDOCS_SEARCH_URL` | MkDocs search endpoint URL | Optional |
| `MKDOCS_SITE_SERVER_PORT` | Port for MkDocs integration | 4002 |
| `PORT` | Server port | 3000 |
| `NODE_ENV` | Environment mode | production |
| `SESSION_SECRET` | Session encryption secret (generate with openssl rand -hex 32) | Required |
| `DEFAULT_LAT` | Default map latitude | 53.5461 |
| `DEFAULT_LNG` | Default map longitude | -113.4938 |
| `DEFAULT_ZOOM` | Default map zoom level | 11 |
| `BOUND_NORTH` | Northern boundary for map points (optional) | None |
| `BOUND_SOUTH` | Southern boundary for map points (optional) | None |
| `BOUND_EAST` | Eastern boundary for map points (optional) | None |
| `BOUND_WEST` | Western boundary for map points (optional) | None |
| `TRUST_PROXY` | Trust proxy headers (for Cloudflare) | true |
| `COOKIE_DOMAIN` | Cookie domain setting | .cmlite.org |
| `ALLOWED_ORIGINS` | CORS allowed origins (comma-separated) | Multiple URLs |
| `SMTP_HOST` | SMTP server hostname (required for email features) | smtp.gmail.com |
| `SMTP_PORT` | SMTP server port (required for email features) | 587 |
| `SMTP_SECURE` | Use SSL for SMTP (required for email features) | false |
| `SMTP_USER` | SMTP username (required for email features) | your-email@gmail.com |
| `SMTP_PASS` | SMTP password (required for email features) | your-app-password |
| `EMAIL_FROM_NAME` | Sender name for outgoing emails | CMlite Support |
| `EMAIL_FROM_ADDRESS` | Sender email address for outgoing emails | noreply@cmlite.org |
| `APP_NAME` | Application name used in emails and branding | CMlite Map |
| `EMAIL_FROM_NAME` | Email sender name (optional) | CMlite Support |
| `EMAIL_FROM_ADDRESS` | Email sender address (optional) | noreply@cmlite.org |
| `APP_NAME` | Application name for emails (optional) | CMlite Map |

## Maintenance Commands

### Update Application
```bash
docker-compose down
git pull origin main
docker-compose build
docker-compose up -d
```

### Development Mode
```bash
cd app
npm install
npm run dev
```

### Health Check
```bash
curl http://localhost:3000/health
```

## Development

To run in development mode:

1. Install dependencies:
   ```bash
   cd app
   npm install
   ```

2. Start with hot reload:
   ```bash
   npm run dev
   ```

## Usage Guide

### Email Features

#### Admin Broadcasting
1. Access the admin panel at `/admin.html` 
2. Navigate to the "User Management" section
3. Click "Email All Users" to open the email composer
4. Use the rich text editor to format your message
5. Preview your email before sending
6. Send to all registered users with delivery tracking

#### Shift Email Notifications
1. In the admin panel, go to "Shift Management"
2. Click "Manage Volunteers" for any shift
3. Add or remove volunteers as needed  
4. Click "Email Shift Details" to notify all volunteers
5. Professional emails include shift details, location, and calendar links

#### User Management
1. Create new users (regular or temporary with expiration)
2. Send login credentials automatically via email
3. Password recovery through secure email notifications
4. Temporary users receive expiration warnings

#### Calendar Integration
- Users can export shifts to Google Calendar, Outlook, or Apple Calendar
- Calendar invites include all shift details and location information
- One-click calendar integration for better volunteer organization

## Security Considerations

- API tokens are kept server-side only
- CORS is configured for security
- Rate limiting prevents abuse
- Input validation on all endpoints
- Helmet.js for security headers

## Troubleshooting

### Locations not showing

- Verify table has `Geo-Location`, `latitude`, and `longitude` columns
- Check that coordinates are valid numbers
- Ensure API token has read permissions

### Cannot add locations

- Verify API token has write permissions
- Check browser console for errors
- Ensure coordinates are within valid ranges

### Connection errors

- Verify NocoDB instance is accessible
- Check API URL format
- Confirm network connectivity

### Build Script Issues

- Ensure NocoDB instance is accessible
- Verify API token has admin permissions
- Check that the NocoDB database is clean (delete all bases before running)

### Email Issues

**Emails not sending:**
- Verify SMTP configuration in `.env` file
- Check SMTP credentials are correct
- Test SMTP connection with your email provider
- Review application logs for email errors

**Gmail SMTP setup:**
1. Enable 2-factor authentication on your Google account
2. Generate an App Password (not your regular password)
3. Use `smtp.gmail.com` as SMTP_HOST with port 587
4. Set SMTP_SECURE to `false` for STARTTLS

**Email templates not rendering:**
- Check that all template files exist in `app/templates/email/`
- Verify template variable names match controller implementations
- Review logs for template rendering errors

**Shift emails not working:**
- Ensure shift signups table is properly configured
- Verify users have valid email addresses
- Check that email templates include all required variables

## License

MIT License - See LICENSE file for details

## Support

For issues or questions:
1. Check the troubleshooting section
2. Review NocoDB documentation
3. Open an issue on GitHub

## Known Bugs 

- First load of page often fails, need to debug 
- Want UI for dots to have an edit button that then brings up the form