# FilterTemplate System

## Problem

En kolonne har en unik nøgle baseret på view-konfigurationen (f.eks. team + resource + date).
Events skal matches mod denne nøgle - men kun på de felter viewet definerer.

## Løsning: FilterTemplate

ViewConfig definerer hvilke felter (idProperties) der indgår i kolonnens nøgle.
Samme template bruges til at bygge nøgle for både kolonne og event.

**Princip:** Kolonnens nøgle-template bestemmer hvad der matches på.

---

## ViewConfig med idProperty

ViewConfig er kilden til sandhed - den definerer grupper OG deres relations-id property.

```typescript
interface GroupingConfig {
  type: string;                 // 'team', 'resource', 'date'
  values: string[];             // ['EMP001', 'EMP002']
  idProperty: string;           // property-navn på event (eks. 'resourceId')
  derivedFrom?: string;         // for date: udledes fra 'start'
}
```

### Eksempler

**Team → Resource → Date view:**
```typescript
{
  groupings: [
    { type: 'team', values: ['team-a'], idProperty: 'teamId' },
    { type: 'resource', values: ['EMP001', 'EMP002'], idProperty: 'resourceId' },
    { type: 'date', values: ['2025-12-09', '2025-12-10'], idProperty: 'date', derivedFrom: 'start' }
  ]
}
```

**Simple date-only view:**
```typescript
{
  groupings: [
    { type: 'date', values: ['2025-12-09', '2025-12-10'], idProperty: 'date', derivedFrom: 'start' }
  ]
}
```

---

## FilterTemplate Klasse

```typescript
class FilterTemplate {
  private fields: Array<{
    idProperty: string;
    derivedFrom?: string;
  }> = [];

  addField(idProperty: string, derivedFrom?: string): this {
    this.fields.push({ idProperty, derivedFrom });
    return this;
  }

  buildKeyFromColumn(column: HTMLElement): string {
    return this.fields
      .map(f => column.dataset[f.idProperty] || '')
      .join(':');
  }

  buildKeyFromEvent(event: ICalendarEvent, dateService: DateService): string {
    return this.fields
      .map(f => {
        if (f.derivedFrom) {
          return dateService.getDateKey((event as any)[f.derivedFrom]);
        }
        return (event as any)[f.idProperty] || '';
      })
      .join(':');
  }
}
```

---

## Flow

```
Orchestrator
    │
    ├── Læs ViewConfig.groupings
    │
    ├── Byg FilterTemplate fra groupings:
    │     for (grouping of viewConfig.groupings) {
    │       template.addField(grouping.idProperty, grouping.derivedFrom);
    │     }
    │
    ├── Kør group-renderers (bygger headers + kolonner)
    │     └── DateRenderer sætter column.dataset[idProperty] for ALLE grupperinger
    │
    └── EventRenderer.render(ctx, template)
            │
            └── for each column:
                    columnKey = template.buildKeyFromColumn(column)
                    columnEvents = events.filter(e =>
                        template.buildKeyFromEvent(e) === columnKey
                    )
```

---

## Eksempler

### 3-niveau view: Team → Resource → Date

**ViewConfig:**
```typescript
groupings: [
  { type: 'team', values: ['team-a'], idProperty: 'teamId' },
  { type: 'resource', values: ['EMP001'], idProperty: 'resourceId' },
  { type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
```

**Template:** `['teamId', 'resourceId', 'date']`

**Kolonne-nøgle:** `"team-a:EMP001:2025-12-09"`
**Event-nøgle:** `"team-a:EMP001:2025-12-09"`

**Match!**

---

### 2-niveau view: Resource → Date

**ViewConfig:**
```typescript
groupings: [
  { type: 'resource', values: ['EMP001'], idProperty: 'resourceId' },
  { type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
```

**Template:** `['resourceId', 'date']`

**Kolonne-nøgle:** `"EMP001:2025-12-09"`
**Event-nøgle:** `"EMP001:2025-12-09"` (teamId ignoreres - ikke i template)

**Match!**

---

### 1-niveau view: Kun Date

**ViewConfig:**
```typescript
groupings: [
  { type: 'date', values: ['2025-12-09'], idProperty: 'date', derivedFrom: 'start' }
]
```

**Template:** `['date']`

**Kolonne-nøgle:** `"2025-12-09"`
**Event-nøgle:** `"2025-12-09"` (alle andre felter ignoreres)

**Match!** Samme event vises i alle views - kun de relevante felter indgår i matching.

---

## Kerneprincipper

1. **ViewConfig definerer nøgle-template** - hvilke idProperties der indgår
2. **Samme template til kolonne og event** - sikrer konsistent matching
3. **Felter udenfor template ignoreres** - event med ekstra felter matcher stadig
4. **idProperty** - eksplicit mapping mellem gruppering og event-felt
5. **derivedFrom** - håndterer felter der udledes (f.eks. date fra start)
