2025-07-24 22:17:38 +02:00
|
|
|
import { EventBus } from '../core/EventBus';
|
2025-08-07 00:15:44 +02:00
|
|
|
import { IEventBus, CalendarEvent, ResourceCalendarData } from '../types/CalendarTypes';
|
2025-07-24 22:17:38 +02:00
|
|
|
import { EventTypes } from '../constants/EventTypes';
|
2025-08-09 00:31:44 +02:00
|
|
|
import { StateEvents } from '../types/CalendarState';
|
2025-08-07 00:15:44 +02:00
|
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* EventManager - Administrerer event lifecycle og CRUD operationer
|
|
|
|
|
* Håndterer mock data og event synchronization
|
|
|
|
|
*/
|
|
|
|
|
export class EventManager {
|
|
|
|
|
private eventBus: IEventBus;
|
|
|
|
|
private events: CalendarEvent[] = [];
|
|
|
|
|
|
|
|
|
|
constructor(eventBus: IEventBus) {
|
2025-08-07 00:15:44 +02:00
|
|
|
console.log('EventManager: Constructor called');
|
2025-07-24 22:17:38 +02:00
|
|
|
this.eventBus = eventBus;
|
|
|
|
|
this.setupEventListeners();
|
2025-08-09 00:31:44 +02:00
|
|
|
console.log('EventManager: Waiting for CALENDAR_INITIALIZED before loading data');
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private setupEventListeners(): void {
|
2025-08-09 00:31:44 +02:00
|
|
|
// Listen for state-driven data loading request
|
|
|
|
|
this.eventBus.on(StateEvents.DATA_LOADING_STARTED, (e: Event) => {
|
|
|
|
|
const detail = (e as CustomEvent).detail;
|
|
|
|
|
console.log('EventManager: Received DATA_LOADING_STARTED, starting data load');
|
|
|
|
|
|
|
|
|
|
this.loadMockData().then(() => {
|
|
|
|
|
console.log('EventManager: loadMockData() completed, emitting DATA_LOADED');
|
|
|
|
|
// Emit state-driven data loaded event
|
|
|
|
|
this.eventBus.emit(StateEvents.DATA_LOADED, {
|
|
|
|
|
type: StateEvents.DATA_LOADED,
|
|
|
|
|
component: 'EventManager',
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
data: {
|
|
|
|
|
eventCount: this.events.length,
|
|
|
|
|
calendarMode: calendarConfig.getCalendarMode(),
|
|
|
|
|
period: detail.data?.period || { start: '', end: '' },
|
|
|
|
|
events: this.events // Include actual events for EventRenderer
|
|
|
|
|
},
|
|
|
|
|
metadata: {
|
|
|
|
|
phase: 'data-loading'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
console.error('EventManager: loadMockData() failed:', error);
|
|
|
|
|
this.eventBus.emit(StateEvents.DATA_FAILED, {
|
|
|
|
|
type: StateEvents.DATA_FAILED,
|
|
|
|
|
component: 'EventManager',
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
error,
|
|
|
|
|
metadata: {
|
|
|
|
|
phase: 'data-loading'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
// Legacy event listeners removed - data is now managed via state-driven events only
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-07 00:15:44 +02:00
|
|
|
private async loadMockData(): Promise<void> {
|
|
|
|
|
try {
|
2025-08-09 00:31:44 +02:00
|
|
|
const calendarType = calendarConfig.getCalendarMode();
|
2025-08-07 00:15:44 +02:00
|
|
|
let jsonFile: string;
|
|
|
|
|
|
|
|
|
|
console.log(`EventManager: Calendar type detected: '${calendarType}'`);
|
|
|
|
|
|
|
|
|
|
if (calendarType === 'resource') {
|
|
|
|
|
jsonFile = '/src/data/mock-resource-events.json';
|
|
|
|
|
} else {
|
|
|
|
|
jsonFile = '/src/data/mock-events.json';
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-07 00:15:44 +02:00
|
|
|
|
|
|
|
|
console.log(`EventManager: Loading ${calendarType} calendar data from ${jsonFile}`);
|
|
|
|
|
|
|
|
|
|
const response = await fetch(jsonFile);
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error(`Failed to load mock events: ${response.status}`);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
const data = await response.json();
|
|
|
|
|
console.log(`EventManager: Loaded data for ${calendarType} calendar`);
|
2025-08-07 00:15:44 +02:00
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
// Remove legacy double emission - data is sent via StateEvents.DATA_LOADED only
|
|
|
|
|
|
|
|
|
|
// Process data for internal use
|
|
|
|
|
this.processCalendarData(calendarType, data);
|
2025-08-07 00:15:44 +02:00
|
|
|
} catch (error) {
|
|
|
|
|
console.error('EventManager: Failed to load mock events:', error);
|
|
|
|
|
this.events = []; // Fallback to empty array
|
|
|
|
|
}
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
private processCalendarData(calendarType: string, data: any): void {
|
|
|
|
|
if (calendarType === 'resource') {
|
|
|
|
|
const resourceData = data as ResourceCalendarData;
|
|
|
|
|
this.events = resourceData.resources.flatMap(resource =>
|
|
|
|
|
resource.events.map(event => ({
|
|
|
|
|
...event,
|
|
|
|
|
resourceName: resource.name,
|
|
|
|
|
resourceDisplayName: resource.displayName,
|
|
|
|
|
resourceEmployeeId: resource.employeeId
|
|
|
|
|
}))
|
|
|
|
|
);
|
|
|
|
|
console.log(`EventManager: Processed ${this.events.length} events from ${resourceData.resources.length} resources`);
|
|
|
|
|
} else {
|
|
|
|
|
this.events = data as CalendarEvent[];
|
|
|
|
|
console.log(`EventManager: Processed ${this.events.length} date events`);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-09 00:31:44 +02:00
|
|
|
private syncEvents(): void {
|
|
|
|
|
// Events are now synced via StateEvents.DATA_LOADED during initialization
|
|
|
|
|
// This method maintained for internal state management only
|
|
|
|
|
console.log(`EventManager: Internal sync - ${this.events.length} events in memory`);
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getEvents(): CalendarEvent[] {
|
|
|
|
|
return [...this.events];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public getEventById(id: string): CalendarEvent | undefined {
|
|
|
|
|
return this.events.find(event => event.id === id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public addEvent(event: Omit<CalendarEvent, 'id'>): CalendarEvent {
|
|
|
|
|
const newEvent: CalendarEvent = {
|
|
|
|
|
...event,
|
|
|
|
|
id: Date.now().toString()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.events.push(newEvent);
|
|
|
|
|
this.syncEvents();
|
|
|
|
|
|
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_CREATED, {
|
|
|
|
|
event: newEvent
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return newEvent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public updateEvent(id: string, updates: Partial<CalendarEvent>): CalendarEvent | null {
|
|
|
|
|
const eventIndex = this.events.findIndex(event => event.id === id);
|
|
|
|
|
if (eventIndex === -1) return null;
|
|
|
|
|
|
|
|
|
|
const updatedEvent = { ...this.events[eventIndex], ...updates };
|
|
|
|
|
this.events[eventIndex] = updatedEvent;
|
|
|
|
|
|
|
|
|
|
this.syncEvents();
|
|
|
|
|
|
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_UPDATED, {
|
|
|
|
|
event: updatedEvent
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return updatedEvent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public deleteEvent(id: string): boolean {
|
|
|
|
|
const eventIndex = this.events.findIndex(event => event.id === id);
|
|
|
|
|
if (eventIndex === -1) return false;
|
|
|
|
|
|
|
|
|
|
const deletedEvent = this.events[eventIndex];
|
|
|
|
|
this.events.splice(eventIndex, 1);
|
|
|
|
|
|
|
|
|
|
this.syncEvents();
|
|
|
|
|
|
|
|
|
|
this.eventBus.emit(EventTypes.EVENT_DELETED, {
|
|
|
|
|
event: deletedEvent
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public refresh(): void {
|
|
|
|
|
this.syncEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
this.events = [];
|
|
|
|
|
}
|
|
|
|
|
}
|