# Sync Hooks Frontend Integration - Date Filter Support

## Problem
The backend sync hooks system requires date filters (e.g., `start_date`, `end_date`) to calculate aggregates, but the frontend `filter-date-range` component only filters data locally in IndexedDB. The filters need to be passed to the backend during sync so hooks can execute with the correct parameters.

## Solution

### 1. Updated LocalSyncManager.bulkPull() ✅
Added support for passing extra query parameters:

```javascript
async bulkPull(tablesMap, extraParams = {}) {
    // ... existing code ...
    
    // Add any extra query parameters (e.g., date filters for hooks)
    for (const [key, value] of Object.entries(extraParams)) {
        if (value != null && value !== '') {
            params.append(key, value);
        }
    }
    
    const url = `${this.bulkEndpoint}/pull?${params.toString()}`;
    // ...
}
```

### 2. Add syncTableWithFilters() Method

Add a new method to LocalSyncManager that triggers a sync with filters:

```javascript
async syncTableWithFilters(tableName, filters = {}) {
    const since = this.lastSyncTimes[tableName] || '';
    const tablesMap = { [tableName]: since };
    return await this.bulkPull(tablesMap, filters);
}
```

### 3. Update DataLoader to Sync With Filters

When date range filters change in DataLoader, trigger a backend sync:

```javascript
// In DataLoader.fetchData() or when filters change:
if (this.hasSyncFilters()) {
    const syncFilters = this.extractSyncFilters();
    await this.syncManager.syncTableWithFilters(this.tableName, syncFilters);
}
```

### 4. Update ModalBuilder filter-date-range Handler

When date range changes, trigger table resync if the table has hooks:

```javascript
// In ModalBuilder when filter-date-range changes:
const tables = this.body.filter(el => el.type === 'table' && el.options.syncFilters);
for (const tableEl of tables) {
    const mgr = await getManager();
    await mgr.syncTableWithFilters(tableEl.options.tableName, {
        start_date: dateRange.from,
        end_date: dateRange.to
    });
}
```

### 5. Module Configuration

Add `syncFilters: true` to table config in modules that need backend filtering:

```sql
UPDATE modules
SET config = jsonb_set(
    config,
    '{body,0,options,syncFilters}',
    'true'
)
WHERE name = 'Payroll'
AND config->'body'->0->>'type' = 'table';
```

## Implementation Steps

1. ✅ Update `LocalSyncManager.bulkPull()` to accept extraParams
2. Add `syncTableWithFilters()` method to LocalSyncManager
3. Update DataLoader to detect date range filters and trigger sync
4. Update ModalBuilder to handle filter changes and trigger sync
5. Update module configs to enable syncFilters
6. Test end-to-end flow

## Example Usage

### Module Config (Payroll):
```json
{
    "header": [
        {
            "type": "filter-date-range",
            "filterField": "start_date",
            "label": "Pay Period"
        }
    ],
    "body": [
        {
            "type": "table",
            "options": {
                "tableName": "time_clock_aggregates",
                "syncFilters": true,
                "syncFilterFields": ["start_date", "end_date"]
            }
        }
    ]
}
```

### Frontend Flow:
1. User opens Payroll module
2. User selects date range (2025-05-01 to 2025-08-31)
3. filter-date-range emits `builderFilterChanged` event
4. ModalBuilder catches event, sees table has `syncFilters: true`
5. Calls `syncTableWithFilters('time_clock_aggregates', { start_date: '2025-05-01', end_date: '2025-08-31' })`
6. Backend receives request with date filters
7. Sync hooks execute with date range
8. Aggregates calculated and returned
9. DataLoader displays the results

## Testing

```javascript
// Test syncTableWithFilters
const mgr = new LocalSyncManager({ bulkEndpoint: '../api/sync' });
await mgr.init();
await mgr.syncTableWithFilters('time_clock_aggregates', {
    start_date: '2025-05-01',
    end_date: '2025-08-31'
});

// Verify request includes filters
expect(fetch).toHaveBeenCalledWith(
    '../api/sync/pull?tables[time_clock_aggregates]=&start_date=2025-05-01&end_date=2025-08-31',
    expect.any(Object)
);
```

## Migration Required

None - this is backward compatible. Tables without `syncFilters: true` continue to work as before.

## Status

- ✅ Step 1: bulkPull updated
- ⏳ Step 2: Add syncTableWithFilters method
- ⏳ Step 3: Update ModalBuilder/DataLoader
- ⏳ Step 4: Update module configs
- ⏳ Step 5: End-to-end testing
