Calendar/src/managers/CalendarManager.ts

372 lines
12 KiB
TypeScript
Raw Normal View History

import { EventBus } from '../core/EventBus.js';
import { EventTypes } from '../constants/EventTypes.js';
import { CalendarConfig } from '../core/CalendarConfig.js';
import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes.js';
2025-08-09 01:16:04 +02:00
import { EventManager } from './EventManager.js';
import { GridManager } from './GridManager.js';
import { EventRenderer } from '../renderers/EventRendererManager.js';
2025-08-09 01:16:04 +02:00
import { ScrollManager } from './ScrollManager.js';
/**
* CalendarManager - Main coordinator for all calendar managers
2025-08-09 01:16:04 +02:00
* Uses simple direct method calls instead of complex state management
*/
export class CalendarManager {
private eventBus: IEventBus;
private config: CalendarConfig;
2025-08-09 01:16:04 +02:00
private eventManager: EventManager;
private gridManager: GridManager;
private eventRenderer: EventRenderer;
private scrollManager: ScrollManager;
private currentView: CalendarView = 'week';
private currentDate: Date = new Date();
private isInitialized: boolean = false;
constructor(eventBus: IEventBus, config: CalendarConfig) {
this.eventBus = eventBus;
this.config = config;
this.setupEventListeners();
2025-08-09 01:16:04 +02:00
console.log('📋 CalendarManager: Created with direct coordination');
}
/**
2025-08-09 01:16:04 +02:00
* Set manager references (called from index.ts)
*/
public setManagers(eventManager: EventManager, gridManager: GridManager, eventRenderer: EventRenderer, scrollManager: ScrollManager): void {
this.eventManager = eventManager;
this.gridManager = gridManager;
this.eventRenderer = eventRenderer;
this.scrollManager = scrollManager;
}
/**
* Initialize calendar system using simple direct calls
*/
public async initialize(): Promise<void> {
if (this.isInitialized) {
console.warn('CalendarManager is already initialized');
return;
}
2025-08-09 01:16:04 +02:00
console.log('🚀 CalendarManager: Starting simple initialization');
try {
// Debug: Check calendar type
const calendarType = this.config.getCalendarMode();
console.log(`🔍 CalendarManager: Initializing ${calendarType} calendar`);
2025-08-09 01:16:04 +02:00
// Step 1: Load data
console.log('📊 Loading event data...');
await this.eventManager.loadData();
// Step 2: Pass data to GridManager and render grid structure
2025-08-09 01:16:04 +02:00
console.log('🏗️ Rendering grid...');
if (calendarType === 'resource') {
const resourceData = this.eventManager.getResourceData();
this.gridManager.setResourceData(resourceData);
}
2025-08-09 01:16:04 +02:00
await this.gridManager.render();
// Step 3: Initialize scroll synchronization
console.log('📜 Setting up scroll synchronization...');
this.scrollManager.initialize();
// Step 4: Set initial view and date BEFORE event rendering
console.log('⚙️ Setting initial view and date...');
this.setView(this.currentView);
this.setCurrentDate(this.currentDate);
// Step 5: Event rendering will be triggered by GRID_RENDERED event
console.log('🎨 Event rendering will be triggered automatically by grid events...');
2025-08-09 01:16:04 +02:00
this.isInitialized = true;
2025-08-09 01:16:04 +02:00
console.log('✅ CalendarManager: Simple initialization complete');
// Emit initialization complete event
this.eventBus.emit(EventTypes.CALENDAR_INITIALIZED, {
currentDate: this.currentDate,
currentView: this.currentView
});
} catch (error) {
console.error('❌ CalendarManager initialization failed:', error);
2025-08-09 01:16:04 +02:00
throw error;
}
}
/**
* Skift calendar view (dag/uge/måned)
*/
public setView(view: CalendarView): void {
if (this.currentView === view) {
return;
}
const previousView = this.currentView;
this.currentView = view;
console.log(`Changing view from ${previousView} to ${view}`);
// Emit view change event
this.eventBus.emit(EventTypes.VIEW_CHANGED, {
previousView,
currentView: view,
date: this.currentDate
});
// Grid re-rendering will trigger event rendering automatically via GRID_RENDERED event
}
/**
* Sæt aktuel dato
*/
public setCurrentDate(date: Date): void {
const previousDate = this.currentDate;
this.currentDate = new Date(date);
console.log(`Changing date from ${previousDate.toISOString()} to ${date.toISOString()}`);
// Emit date change event
this.eventBus.emit(EventTypes.DATE_CHANGED, {
previousDate,
currentDate: this.currentDate,
view: this.currentView
});
// Grid update for new date will trigger event rendering automatically via GRID_RENDERED event
}
/**
* Naviger til i dag
*/
public goToToday(): void {
this.setCurrentDate(new Date());
}
/**
* Naviger til næste periode (dag/uge/måned afhængig af view)
*/
public goToNext(): void {
const nextDate = this.calculateNextDate();
this.setCurrentDate(nextDate);
}
/**
* Naviger til forrige periode (dag/uge/måned afhængig af view)
*/
public goToPrevious(): void {
const previousDate = this.calculatePreviousDate();
this.setCurrentDate(previousDate);
}
/**
* Hent aktuel view
*/
public getCurrentView(): CalendarView {
return this.currentView;
}
/**
* Hent aktuel dato
*/
public getCurrentDate(): Date {
return new Date(this.currentDate);
}
/**
* Hent calendar konfiguration
*/
public getConfig(): CalendarConfig {
return this.config;
}
/**
* Check om calendar er initialiseret
*/
public isCalendarInitialized(): boolean {
2025-08-09 01:16:04 +02:00
return this.isInitialized;
}
/**
* Get initialization report for debugging
*/
public getInitializationReport(): any {
2025-08-09 01:16:04 +02:00
return {
isInitialized: this.isInitialized,
currentView: this.currentView,
currentDate: this.currentDate,
initializationTime: 'N/A - simple initialization'
};
}
/**
* Genindlæs calendar data
*/
public refresh(): void {
console.log('Refreshing calendar...');
this.eventBus.emit(EventTypes.CALENDAR_REFRESH_REQUESTED, {
view: this.currentView,
date: this.currentDate
});
}
/**
* Ryd calendar og nulstil til standard tilstand
*/
public reset(): void {
console.log('Resetting calendar...');
this.currentView = 'week';
this.currentDate = new Date();
this.eventBus.emit(EventTypes.CALENDAR_RESET, {
view: this.currentView,
date: this.currentDate
});
}
/**
* Setup event listeners for at håndtere events fra andre managers
*/
private setupEventListeners(): void {
// Lyt efter navigation events
this.eventBus.on(EventTypes.NAVIGATE_TO_DATE, (event) => {
const customEvent = event as CustomEvent;
const { date } = customEvent.detail;
this.setCurrentDate(new Date(date));
});
// Lyt efter view change requests
this.eventBus.on(EventTypes.VIEW_CHANGE_REQUESTED, (event) => {
const customEvent = event as CustomEvent;
const { view } = customEvent.detail;
this.setView(view);
});
// Lyt efter today navigation
this.eventBus.on(EventTypes.NAVIGATE_TO_TODAY, () => {
this.goToToday();
});
// Lyt efter next/previous navigation
this.eventBus.on(EventTypes.NAVIGATE_NEXT, () => {
this.goToNext();
});
this.eventBus.on(EventTypes.NAVIGATE_PREVIOUS, () => {
this.goToPrevious();
});
// Lyt efter refresh requests
this.eventBus.on(EventTypes.REFRESH_REQUESTED, () => {
this.refresh();
});
// Lyt efter reset requests
this.eventBus.on(EventTypes.RESET_REQUESTED, () => {
this.reset();
});
}
/**
* Beregn næste dato baseret aktuel view
*/
private calculateNextDate(): Date {
const nextDate = new Date(this.currentDate);
switch (this.currentView) {
case 'day':
nextDate.setDate(nextDate.getDate() + 1);
break;
case 'week':
nextDate.setDate(nextDate.getDate() + 7);
break;
case 'month':
nextDate.setMonth(nextDate.getMonth() + 1);
break;
}
return nextDate;
}
/**
* Beregn forrige dato baseret aktuel view
*/
private calculatePreviousDate(): Date {
const previousDate = new Date(this.currentDate);
switch (this.currentView) {
case 'day':
previousDate.setDate(previousDate.getDate() - 1);
break;
case 'week':
previousDate.setDate(previousDate.getDate() - 7);
break;
case 'month':
previousDate.setMonth(previousDate.getMonth() - 1);
break;
}
return previousDate;
}
/**
* Calculate the current period based on view and date
*/
private calculateCurrentPeriod(): { start: string; end: string } {
const current = new Date(this.currentDate);
switch (this.currentView) {
case 'day':
const dayStart = new Date(current);
dayStart.setHours(0, 0, 0, 0);
const dayEnd = new Date(current);
dayEnd.setHours(23, 59, 59, 999);
return {
start: dayStart.toISOString(),
end: dayEnd.toISOString()
};
case 'week':
// Find start of week (Monday)
const weekStart = new Date(current);
const dayOfWeek = weekStart.getDay();
const daysToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Sunday = 0, so 6 days back to Monday
weekStart.setDate(weekStart.getDate() - daysToMonday);
weekStart.setHours(0, 0, 0, 0);
// Find end of week (Sunday)
const weekEnd = new Date(weekStart);
weekEnd.setDate(weekEnd.getDate() + 6);
weekEnd.setHours(23, 59, 59, 999);
return {
start: weekStart.toISOString(),
end: weekEnd.toISOString()
};
case 'month':
const monthStart = new Date(current.getFullYear(), current.getMonth(), 1);
const monthEnd = new Date(current.getFullYear(), current.getMonth() + 1, 0, 23, 59, 59, 999);
return {
start: monthStart.toISOString(),
end: monthEnd.toISOString()
};
default:
// Fallback to week view
const fallbackStart = new Date(current);
fallbackStart.setDate(fallbackStart.getDate() - 3);
fallbackStart.setHours(0, 0, 0, 0);
const fallbackEnd = new Date(current);
fallbackEnd.setDate(fallbackEnd.getDate() + 3);
fallbackEnd.setHours(23, 59, 59, 999);
return {
start: fallbackStart.toISOString(),
end: fallbackEnd.toISOString()
};
}
}
}