# Generic GPS Map Component

## Overview

The `GpsMapViewer` is a reusable GPS mapping component that works with **any table** containing latitude/longitude coordinates. It integrates seamlessly with ModalBuilder and can be configured entirely through JSON in the `modules` table.

## Features

✅ **Generic & Reusable** - Works with any table with GPS coordinates  
✅ **Google Maps Integration** - Full Google Maps API support  
✅ **Color-Coded Markers** - Different colors based on record type  
✅ **Chronological Paths** - Shows movement trail between points  
✅ **Info Windows** - Customizable popups with record details  
✅ **Filter Integration** - Responds to date ranges and field filters  
✅ **Template System** - Dynamic content via `{{field}}` placeholders  

---

## Quick Start

### 1. Add GPS Map to Module

```json
{
  "type": "gps-map",
  "id": "myGpsMap",
  "options": {
    "tableName": "time_clocks",
    "latField": "latitude",
    "lngField": "longitude",
    "timestampField": "clocked_at",
    "filterField": "user_id"
  }
}
```

### 2. Enable Google Maps

Add to module config:

```json
{
  "mapLibraries": {
    "provider": "google",
    "libraries": "geometry"
  }
}
```

---

## Configuration Options

### Required Options

| Option | Type | Description |
|--------|------|-------------|
| `tableName` | string | IndexedDB table to query (e.g., `time_clocks`) |
| `latField` | string | Column name for latitude (default: `latitude`) |
| `lngField` | string | Column name for longitude (default: `longitude`) |

### Filter Options

| Option | Type | Description |
|--------|------|-------------|
| `filterField` | string | Field to filter by (e.g., `user_id`) |
| `filterValue` | any | Value to match for `filterField` |
| `listenColumn` | string | Column to listen for filter events |
| `dateRangeField` | string | Date field for range filtering |
| `dateRange` | object | `{start: "2025-01-01", end: "2025-12-31"}` |

### Display Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `timestampField` | string | `created_at` | Field for chronological sorting |
| `typeField` | string | `null` | Field to determine marker color |
| `defaultZoom` | number | `12` | Initial map zoom level |
| `height` | string | `600px` | Map container height |
| `showPath` | boolean | `true` | Draw line connecting markers |
| `pathColor` | string | `#3b82f6` | Color of the path line |
| `showInfoWindow` | boolean | `true` | Show popups on marker click |

### Marker Configuration

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `markerColors` | object | See below | Color map for marker types |
| `labelField` | string | `null` | Field to use for marker labels |

**Default Marker Colors:**
```json
{
  "default": "#3b82f6",
  "in": "#10b981",
  "out": "#ef4444"
}
```

### Template Options

| Option | Type | Description |
|--------|------|-------------|
| `titleTemplate` | string | Marker title template (e.g., `"{{clock_type}} - {{clocked_at}}"`) |
| `infoWindowTemplate` | string | Info window HTML template |

**Available Template Variables:**
- `{{index}}` - Marker number (1-based)
- `{{lat}}` - Latitude (6 decimals)
- `{{lng}}` - Longitude (6 decimals)
- `{{field_name}}` - Any field from the record

---

## Examples

### 1. Payroll Time Clock Map

```json
{
  "type": "gps-map",
  "id": "timeClockMap",
  "options": {
    "tableName": "time_clocks",
    "latField": "latitude",
    "lngField": "longitude",
    "timestampField": "clocked_at",
    "typeField": "clock_type",
    "filterField": "user_id",
    "listenColumn": "user_id",
    "dateRangeField": "clocked_at",
    "markerColors": {
      "in": "#10b981",
      "out": "#ef4444"
    },
    "showPath": true,
    "titleTemplate": "{{clock_type}} - {{clocked_at}}",
    "infoWindowTemplate": "<div class='p-3'><h3>{{clock_type}} Event</h3><p>Time: {{clocked_at}}</p><p>Location: {{location_name}}</p></div>"
  }
}
```

### 2. Vehicle Tracking

```json
{
  "type": "gps-map",
  "options": {
    "tableName": "vehicle_locations",
    "latField": "lat",
    "lngField": "lng",
    "timestampField": "timestamp",
    "filterField": "vehicle_id",
    "showPath": true,
    "pathColor": "#10b981",
    "markerColors": {
      "moving": "#10b981",
      "stopped": "#fbbf24",
      "default": "#3b82f6"
    }
  }
}
```

### 3. Site Inspections

```json
{
  "type": "gps-map",
  "options": {
    "tableName": "ohs_inspections",
    "latField": "latitude",
    "lngField": "longitude",
    "timestampField": "inspection_date",
    "typeField": "status",
    "filterField": "inspector_id",
    "showPath": false,
    "markerColors": {
      "pending": "#fbbf24",
      "complete": "#10b981",
      "failed": "#ef4444"
    }
  }
}
```

### 4. Delivery Routes

```json
{
  "type": "gps-map",
  "options": {
    "tableName": "delivery_checkpoints",
    "latField": "latitude",
    "lngField": "longitude",
    "timestampField": "checkpoint_time",
    "typeField": "checkpoint_type",
    "filterField": "delivery_id",
    "showPath": true,
    "markerColors": {
      "pickup": "#10b981",
      "waypoint": "#3b82f6",
      "delivery": "#ef4444"
    }
  }
}
```

---

## Integration with Tabs

GPS maps work seamlessly with tab navigation and filter synchronization:

```json
{
  "type": "tabs",
  "tabs": [
    {
      "label": "List",
      "elements": [
        {
          "type": "table",
          "options": {
            "tableName": "records",
            "rowClick": "selectRecord"
          }
        }
      ]
    },
    {
      "label": "Map",
      "elements": [
        {
          "type": "gps-map",
          "options": {
            "tableName": "records",
            "filterField": "record_id",
            "listenColumn": "record_id"
          }
        }
      ]
    }
  ]
}
```

---

## Event Integration

The GPS map component listens for filter events:

```javascript
// Trigger map update
window.dispatchEvent(new CustomEvent('builderFilterChanged', {
  detail: {
    column: 'user_id',
    value: '123-456-789',
    tableName: 'time_clocks'
  }
}));
```

---

## Programmatic Usage

While the component is designed for JSON configuration, you can also use it programmatically:

```javascript
import { GpsMapViewer } from 'components/GpsMapViewer';

const mapViewer = new GpsMapViewer({
  containerId: 'myMapContainer',
  tableName: 'time_clocks',
  latField: 'latitude',
  lngField: 'longitude',
  filterField: 'user_id',
  filterValue: 'abc-123'
});

await mapViewer.render();

// Update filters
await mapViewer.updateFilters({
  filterValue: 'xyz-789',
  dateRange: { start: '2025-01-01', end: '2025-12-31' }
});

// Cleanup
mapViewer.destroy();
```

---

## Files

| File | Purpose |
|------|---------|
| `FrontEnd/js/components/GpsMapViewer.js` | Core GPS map component |
| `FrontEnd/js/core/ModalBuilder.js` | Integration with module system |
| `FrontEnd/js/modules/PayrollTimeClockHandler.js` | Payroll-specific helpers |
| `sql/modules.sql` | Payroll module configuration |
| `sql/defaults.sql` | Time Clock Entry form |

---

## Requirements

- **Google Maps API** - Must be loaded in Dashboard.html
- **IndexedDB** - Records stored in `taf_db`
- **Module System** - ModalBuilder and module registry

---

## Security & Performance

- ✅ GPS coordinates are readonly in edit forms
- ✅ Records filtered by `isdeleted = false`
- ✅ Markers limited to valid lat/lng values
- ✅ Info windows close previous ones automatically
- ✅ Cleanup on component destroy

---

## Troubleshooting

### Map not loading
- Check Google Maps API key in Dashboard.html
- Verify `mapLibraries` in module config
- Open browser console for errors

### No markers showing
- Verify records have valid lat/lng values
- Check `filterField` and `filterValue` match records
- Ensure `isdeleted` is false on records

### Path not drawing
- Verify `timestampField` exists and has valid dates
- Set `showPath: true` in config
- Need at least 2 markers for path

### Template variables not working
- Use exact field names from database
- Format: `{{field_name}}` (double braces)
- Check for typos in field names

---

## Future Enhancements

- [ ] Heatmap overlay option
- [ ] Cluster markers for dense areas
- [ ] Export route as KML/GPX
- [ ] Geofencing alerts
- [ ] Drawing tools integration
- [ ] Multiple path colors
- [ ] Custom marker icons

---

## Support

For questions or issues:
1. Check browser console for errors
2. Verify module configuration JSON
3. Test with minimal config first
4. Review example implementations above
