Calendar/packages/calendar/src/core/BaseGroupingRenderer.ts
Janus C. H. Knudsen ceb44446f0 Sets up calendar package with core infrastructure
Adds core calendar package components including:
- Base services for events, resources, and settings
- Calendar app and orchestrator
- Build and bundling configuration
- IndexedDB storage setup

Prepares foundational architecture for calendar functionality
2026-01-28 15:24:03 +01:00

91 lines
2.9 KiB
TypeScript

import { IRenderer, IRenderContext } from './IGroupingRenderer';
/**
* Entity must have id
*/
export interface IGroupingEntity {
id: string;
}
/**
* Configuration for a grouping renderer
*/
export interface IGroupingRendererConfig {
elementTag: string; // e.g., 'swp-team-header'
idAttribute: string; // e.g., 'teamId' -> data-team-id
colspanVar: string; // e.g., '--team-cols'
}
/**
* Abstract base class for grouping renderers
*
* Handles:
* - Fetching entities by IDs
* - Calculating colspan from parentChildMap
* - Creating header elements
* - Appending to container
*
* Subclasses override:
* - renderHeader() for custom content
* - getDisplayName() for entity display text
*/
export abstract class BaseGroupingRenderer<T extends IGroupingEntity> implements IRenderer {
abstract readonly type: string;
protected abstract readonly config: IGroupingRendererConfig;
/**
* Fetch entities from service
*/
protected abstract getEntities(ids: string[]): Promise<T[]>;
/**
* Get display name for entity
*/
protected abstract getDisplayName(entity: T): string;
/**
* Main render method - handles common logic
*/
async render(context: IRenderContext): Promise<void> {
const allowedIds = context.filter[this.type] || [];
if (allowedIds.length === 0) return;
const entities = await this.getEntities(allowedIds);
const dateCount = context.filter['date']?.length || 1;
const childIds = context.childType ? context.filter[context.childType] || [] : [];
for (const entity of entities) {
const entityChildIds = context.parentChildMap?.[entity.id] || [];
const childCount = entityChildIds.filter(id => childIds.includes(id)).length;
const colspan = childCount * dateCount;
const header = document.createElement(this.config.elementTag);
header.dataset[this.config.idAttribute] = entity.id;
header.style.setProperty(this.config.colspanVar, String(colspan));
// Allow subclass to customize header content
this.renderHeader(entity, header, context);
context.headerContainer.appendChild(header);
}
}
/**
* Override this method for custom header rendering
* Default: just sets textContent to display name
*/
protected renderHeader(entity: T, header: HTMLElement, _context: IRenderContext): void {
header.textContent = this.getDisplayName(entity);
}
/**
* Helper to render a single entity header.
* Can be used by subclasses that override render() but want consistent header creation.
*/
protected createHeader(entity: T, context: IRenderContext): HTMLElement {
const header = document.createElement(this.config.elementTag);
header.dataset[this.config.idAttribute] = entity.id;
this.renderHeader(entity, header, context);
return header;
}
}