2025-07-24 22:17:38 +02:00
|
|
|
import { EventBus } from '../core/EventBus';
|
|
|
|
|
import { IEventBus, CalendarEvent } from '../types/CalendarTypes';
|
|
|
|
|
import { EventTypes } from '../constants/EventTypes';
|
2025-08-09 00:31:44 +02:00
|
|
|
import { StateEvents } from '../types/CalendarState';
|
2025-07-24 22:17:38 +02:00
|
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
2025-08-07 00:15:44 +02:00
|
|
|
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
/**
|
2025-08-07 00:15:44 +02:00
|
|
|
* EventRenderer - Render events i DOM med positionering using Strategy Pattern
|
2025-07-24 22:17:38 +02:00
|
|
|
* Håndterer event positioning og overlap detection
|
|
|
|
|
*/
|
|
|
|
|
export class EventRenderer {
|
|
|
|
|
private eventBus: IEventBus;
|
2025-08-07 00:15:44 +02:00
|
|
|
private pendingEvents: CalendarEvent[] = [];
|
2025-08-09 00:31:44 +02:00
|
|
|
private dataReady: boolean = false;
|
|
|
|
|
private gridReady: boolean = false;
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
constructor(eventBus: IEventBus) {
|
|
|
|
|
this.eventBus = eventBus;
|
|
|
|
|
this.setupEventListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setupEventListeners(): void {
|
2025-08-09 00:31:44 +02:00
|
|
|
// Listen for state-driven data loaded event
|
|
|
|
|
this.eventBus.on(StateEvents.DATA_LOADED, (event: Event) => {
|
2025-07-24 22:17:38 +02:00
|
|
|
const customEvent = event as CustomEvent;
|
2025-08-09 00:31:44 +02:00
|
|
|
// Events are in customEvent.detail (direct from StateEvent payload)
|
|
|
|
|
const eventCount = customEvent.detail.data?.eventCount || 0;
|
|
|
|
|
const events = customEvent.detail.data?.events || [];
|
|
|
|
|
console.log('EventRenderer: Received DATA_LOADED with', eventCount, 'events');
|
|
|
|
|
this.pendingEvents = events; // Store the actual events
|
|
|
|
|
this.dataReady = true;
|
2025-07-25 23:31:25 +02:00
|
|
|
this.tryRenderEvents();
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
// Listen for state-driven grid rendered event
|
|
|
|
|
this.eventBus.on(StateEvents.GRID_RENDERED, (event: Event) => {
|
|
|
|
|
const customEvent = event as CustomEvent;
|
|
|
|
|
console.log('EventRenderer: Received GRID_RENDERED');
|
|
|
|
|
this.gridReady = true;
|
2025-07-25 23:31:25 +02:00
|
|
|
this.tryRenderEvents();
|
2025-07-24 22:17:38 +02:00
|
|
|
});
|
|
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
this.eventBus.on(EventTypes.VIEW_RENDERED, () => {
|
|
|
|
|
// Clear existing events when view changes
|
|
|
|
|
this.clearEvents();
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
// Handle calendar type changes
|
|
|
|
|
this.eventBus.on(EventTypes.CALENDAR_TYPE_CHANGED, () => {
|
|
|
|
|
// Re-render events with new strategy
|
|
|
|
|
this.tryRenderEvents();
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-07-25 23:31:25 +02:00
|
|
|
|
|
|
|
|
private tryRenderEvents(): void {
|
2025-08-09 00:31:44 +02:00
|
|
|
// Only render if we have both data and grid ready
|
|
|
|
|
console.log('EventRenderer: tryRenderEvents called', {
|
|
|
|
|
dataReady: this.dataReady,
|
|
|
|
|
gridReady: this.gridReady,
|
|
|
|
|
pendingEvents: this.pendingEvents.length
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!this.dataReady || !this.gridReady) {
|
|
|
|
|
console.log('EventRenderer: Waiting - data ready:', this.dataReady, 'grid ready:', this.gridReady);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-07 00:15:44 +02:00
|
|
|
|
2025-07-25 23:31:25 +02:00
|
|
|
if (this.pendingEvents.length > 0) {
|
2025-08-09 00:31:44 +02:00
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
2025-08-07 00:15:44 +02:00
|
|
|
let columnsSelector = calendarType === 'resource' ? 'swp-resource-column' : 'swp-day-column';
|
|
|
|
|
const columns = document.querySelectorAll(columnsSelector);
|
|
|
|
|
|
|
|
|
|
console.log(`EventRenderer: Found ${columns.length} ${columnsSelector} elements for ${calendarType} calendar`);
|
|
|
|
|
|
|
|
|
|
if (columns.length > 0) {
|
2025-08-09 00:31:44 +02:00
|
|
|
console.log('🎨 EventRenderer: Both data and grid ready, rendering events!');
|
|
|
|
|
const eventCount = this.pendingEvents.length;
|
2025-07-25 23:31:25 +02:00
|
|
|
this.renderEvents(this.pendingEvents);
|
|
|
|
|
this.pendingEvents = []; // Clear pending events after rendering
|
2025-08-09 00:31:44 +02:00
|
|
|
|
|
|
|
|
// Emit events rendered event
|
|
|
|
|
this.eventBus.emit(StateEvents.EVENTS_RENDERED, {
|
|
|
|
|
type: StateEvents.EVENTS_RENDERED,
|
|
|
|
|
component: 'EventRenderer',
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
data: {
|
|
|
|
|
eventCount,
|
|
|
|
|
calendarMode: calendarType,
|
|
|
|
|
renderMethod: 'state-driven'
|
|
|
|
|
},
|
|
|
|
|
metadata: {
|
|
|
|
|
phase: 'event-rendering'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log('EventRenderer: Grid not ready yet, columns not found');
|
2025-07-25 23:31:25 +02:00
|
|
|
}
|
2025-08-09 00:31:44 +02:00
|
|
|
} else {
|
|
|
|
|
console.log('EventRenderer: No pending events to render');
|
2025-07-25 23:31:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
private renderEvents(events: CalendarEvent[]): void {
|
2025-08-02 23:59:52 +02:00
|
|
|
console.log('EventRenderer: renderEvents called with', events.length, 'events');
|
2025-08-05 00:41:59 +02:00
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
// Get the appropriate event renderer strategy
|
2025-08-09 00:31:44 +02:00
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
2025-08-07 00:15:44 +02:00
|
|
|
const eventRenderer = CalendarTypeFactory.getEventRenderer(calendarType);
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
console.log(`EventRenderer: Using ${calendarType} event renderer strategy`);
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
// Use strategy to render events
|
|
|
|
|
eventRenderer.renderEvents(events, calendarConfig);
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
// Emit event rendered
|
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_RENDERED, {
|
|
|
|
|
count: events.filter(e => !e.allDay).length
|
2025-07-24 22:17:38 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private clearEvents(): void {
|
2025-08-09 00:31:44 +02:00
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
2025-08-07 00:15:44 +02:00
|
|
|
const eventRenderer = CalendarTypeFactory.getEventRenderer(calendarType);
|
|
|
|
|
eventRenderer.clearEvents();
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public refresh(): void {
|
2025-08-07 00:15:44 +02:00
|
|
|
this.tryRenderEvents();
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
2025-08-07 00:15:44 +02:00
|
|
|
this.pendingEvents = [];
|
2025-07-24 22:17:38 +02:00
|
|
|
this.clearEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|