Calendar/src/v2/features/event/EventRenderer.ts

72 lines
2.3 KiB
TypeScript
Raw Normal View History

2025-12-06 01:22:04 +01:00
import { IGroupingRenderer } from '../../core/IGroupingRenderer';
import { RenderContext } from '../../core/RenderContext';
export interface IEventData {
id: string;
title: string;
start: Date;
end: Date;
type?: string;
allDay?: boolean;
}
export interface IEventStore {
getByDateAndResource(date: string, resourceId?: string): Promise<IEventData[]>;
}
export class EventRenderer implements IGroupingRenderer {
readonly type = 'event';
constructor(
private eventStore: IEventStore,
private hourHeight = 60,
private dayStartHour = 6
) {}
render(context: RenderContext): void {
this.renderAsync(context);
}
private async renderAsync(context: RenderContext): Promise<void> {
const columns = context.columnContainer.querySelectorAll<HTMLElement>('swp-day-column');
for (const column of columns) {
const dateStr = column.dataset.date;
if (!dateStr) continue;
const eventsLayer = column.querySelector('swp-events-layer');
if (!eventsLayer) continue;
const events = await this.eventStore.getByDateAndResource(dateStr, column.dataset.parentId);
for (const event of events) {
if (event.allDay) continue;
const { top, height } = this.calculatePosition(event.start, event.end);
const el = document.createElement('swp-event');
el.dataset.eventId = event.id;
el.dataset.type = event.type || 'work';
el.style.cssText = `position:absolute;top:${top}px;height:${height}px;left:2px;right:2px`;
el.innerHTML = `
<swp-event-time>${this.formatTime(event.start)} - ${this.formatTime(event.end)}</swp-event-time>
<swp-event-title>${event.title}</swp-event-title>
`;
eventsLayer.appendChild(el);
}
}
}
private calculatePosition(start: Date, end: Date) {
const startMin = start.getHours() * 60 + start.getMinutes() - this.dayStartHour * 60;
const endMin = end.getHours() * 60 + end.getMinutes() - this.dayStartHour * 60;
return {
top: (startMin / 60) * this.hourHeight,
height: Math.max(((endMin - startMin) / 60) * this.hourHeight, 15)
};
}
private formatTime(d: Date): string {
return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
}
}