2025-07-24 22:17:38 +02:00
|
|
|
import { EventBus } from '../core/EventBus';
|
2025-08-16 00:51:12 +02:00
|
|
|
import { IEventBus, CalendarEvent, RenderContext } from '../types/CalendarTypes';
|
2025-08-20 19:52:18 +02:00
|
|
|
import { CoreEvents } from '../constants/CoreEvents';
|
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-08-17 22:54:00 +02:00
|
|
|
import { EventManager } from '../managers/EventManager';
|
|
|
|
|
import { EventRendererStrategy } from './EventRenderer';
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
/**
|
2025-08-17 23:44:30 +02:00
|
|
|
* EventRenderingService - Render events i DOM med positionering using Strategy Pattern
|
2025-07-24 22:17:38 +02:00
|
|
|
* Håndterer event positioning og overlap detection
|
|
|
|
|
*/
|
2025-08-17 23:44:30 +02:00
|
|
|
export class EventRenderingService {
|
2025-07-24 22:17:38 +02:00
|
|
|
private eventBus: IEventBus;
|
2025-08-16 00:51:12 +02:00
|
|
|
private eventManager: EventManager;
|
|
|
|
|
private strategy: EventRendererStrategy;
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
constructor(eventBus: IEventBus, eventManager: EventManager) {
|
2025-07-24 22:17:38 +02:00
|
|
|
this.eventBus = eventBus;
|
2025-08-16 00:51:12 +02:00
|
|
|
this.eventManager = eventManager;
|
|
|
|
|
|
|
|
|
|
// Cache strategy at initialization
|
|
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
|
|
|
|
this.strategy = CalendarTypeFactory.getEventRenderer(calendarType);
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
this.setupEventListeners();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
/**
|
2025-08-16 00:51:12 +02:00
|
|
|
* Render events in a specific container for a given period
|
2025-08-09 01:16:04 +02:00
|
|
|
*/
|
2025-08-16 00:51:12 +02:00
|
|
|
public renderEvents(context: RenderContext): void {
|
2025-08-20 00:39:31 +02:00
|
|
|
console.log(` 📅 Getting events for ${context.startDate.toDateString()} - ${context.endDate.toDateString()}`);
|
2025-08-05 00:41:59 +02:00
|
|
|
|
2025-08-20 20:22:51 +02:00
|
|
|
// Clear existing events in the specific container first
|
|
|
|
|
this.strategy.clearEvents(context.container);
|
|
|
|
|
console.log(` 🧹 Cleared existing events in container`);
|
|
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
// Get events from EventManager for the period
|
|
|
|
|
const events = this.eventManager.getEventsForPeriod(
|
|
|
|
|
context.startDate,
|
|
|
|
|
context.endDate
|
|
|
|
|
);
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-20 00:39:31 +02:00
|
|
|
console.log(` 📊 Found ${events.length} events for period`);
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
if (events.length === 0) {
|
2025-08-20 00:39:31 +02:00
|
|
|
console.log(' ⚠️ No events to render for this period');
|
2025-08-16 00:51:12 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2025-08-09 01:16:04 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
// Use cached strategy to render events in the specific container
|
|
|
|
|
this.strategy.renderEvents(events, context.container, calendarConfig);
|
2025-08-09 01:16:04 +02:00
|
|
|
|
2025-08-20 00:39:31 +02:00
|
|
|
console.log(` ✅ Rendered ${events.length} events successfully`);
|
2025-08-23 00:01:59 +02:00
|
|
|
|
|
|
|
|
// Emit EVENTS_RENDERED event for filtering system
|
|
|
|
|
this.eventBus.emit(CoreEvents.EVENTS_RENDERED, {
|
|
|
|
|
events: events,
|
|
|
|
|
container: context.container
|
|
|
|
|
});
|
2025-08-09 01:16:04 +02:00
|
|
|
}
|
2025-08-02 23:59:52 +02:00
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
private setupEventListeners(): void {
|
2025-08-16 00:51:12 +02:00
|
|
|
// Event-driven rendering: React to grid and container events
|
2025-08-20 19:52:18 +02:00
|
|
|
this.eventBus.on(CoreEvents.GRID_RENDERED, (event: Event) => {
|
2025-08-20 20:22:51 +02:00
|
|
|
console.log('EventRenderer: Received GRID_RENDERED event');
|
2025-08-16 00:51:12 +02:00
|
|
|
this.handleGridRendered(event as CustomEvent);
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-20 00:39:31 +02:00
|
|
|
// CONTAINER_READY_FOR_EVENTS removed - events are now pre-rendered synchronously
|
|
|
|
|
// this.eventBus.on(EventTypes.CONTAINER_READY_FOR_EVENTS, (event: Event) => {
|
|
|
|
|
// console.log('EventRenderer: Received CONTAINER_READY_FOR_EVENTS event');
|
|
|
|
|
// this.handleContainerReady(event as CustomEvent);
|
|
|
|
|
// });
|
2025-08-16 00:51:12 +02:00
|
|
|
|
2025-08-20 20:22:51 +02:00
|
|
|
this.eventBus.on(CoreEvents.VIEW_CHANGED, (event: Event) => {
|
2025-08-16 00:51:12 +02:00
|
|
|
console.log('EventRenderer: Received VIEW_CHANGED event');
|
|
|
|
|
this.handleViewChanged(event as CustomEvent);
|
2025-08-09 01:16:04 +02:00
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-09 01:16:04 +02:00
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
/**
|
|
|
|
|
* Handle GRID_RENDERED event - render events in the current grid
|
|
|
|
|
*/
|
|
|
|
|
private handleGridRendered(event: CustomEvent): void {
|
2025-08-20 19:52:18 +02:00
|
|
|
const { container, startDate, endDate, currentDate } = event.detail;
|
2025-08-16 00:51:12 +02:00
|
|
|
|
|
|
|
|
if (!container) {
|
|
|
|
|
console.error('EventRenderer: No container in GRID_RENDERED event', event.detail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
let periodStart: Date;
|
|
|
|
|
let periodEnd: Date;
|
|
|
|
|
|
|
|
|
|
if (startDate && endDate) {
|
2025-08-20 21:51:49 +02:00
|
|
|
// Direct date format - use as provided
|
2025-08-20 19:52:18 +02:00
|
|
|
periodStart = startDate;
|
|
|
|
|
periodEnd = endDate;
|
|
|
|
|
} else if (currentDate) {
|
2025-08-20 21:51:49 +02:00
|
|
|
console.error('EventRenderer: GRID_RENDERED events must include explicit startDate and endDate', event.detail);
|
|
|
|
|
return;
|
2025-08-20 19:52:18 +02:00
|
|
|
} else {
|
|
|
|
|
console.error('EventRenderer: No date information in GRID_RENDERED event', event.detail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-16 00:51:12 +02:00
|
|
|
|
|
|
|
|
this.renderEvents({
|
|
|
|
|
container: container,
|
|
|
|
|
startDate: periodStart,
|
|
|
|
|
endDate: periodEnd
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle CONTAINER_READY_FOR_EVENTS event - render events in pre-rendered container
|
|
|
|
|
*/
|
|
|
|
|
private handleContainerReady(event: CustomEvent): void {
|
|
|
|
|
const { container, startDate, endDate } = event.detail;
|
|
|
|
|
|
|
|
|
|
if (!container || !startDate || !endDate) {
|
|
|
|
|
console.error('EventRenderer: Invalid CONTAINER_READY_FOR_EVENTS event data', event.detail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.renderEvents({
|
|
|
|
|
container: container,
|
|
|
|
|
startDate: new Date(startDate),
|
|
|
|
|
endDate: new Date(endDate)
|
|
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-16 00:51:12 +02:00
|
|
|
/**
|
|
|
|
|
* Handle VIEW_CHANGED event - clear and re-render for new view
|
|
|
|
|
*/
|
|
|
|
|
private handleViewChanged(event: CustomEvent): void {
|
|
|
|
|
// Clear all existing events since view structure may have changed
|
2025-08-09 01:16:04 +02:00
|
|
|
this.clearEvents();
|
2025-08-16 00:51:12 +02:00
|
|
|
|
|
|
|
|
// New rendering will be triggered by subsequent GRID_RENDERED event
|
|
|
|
|
console.log('EventRenderer: Cleared events for view change, waiting for GRID_RENDERED');
|
|
|
|
|
}
|
|
|
|
|
private clearEvents(container?: HTMLElement): void {
|
|
|
|
|
console.log(`EventRenderer: Clearing events`, container ? 'in container' : 'globally');
|
|
|
|
|
this.strategy.clearEvents(container);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public refresh(container?: HTMLElement): void {
|
|
|
|
|
// Clear events in specific container or globally
|
|
|
|
|
this.clearEvents(container);
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
this.clearEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|