Calendar/src/managers/GridManager.ts

259 lines
7.3 KiB
TypeScript
Raw Normal View History

/**
* GridManager - Simplified grid manager using Strategy Pattern
* Now delegates view-specific logic to strategy implementations
*/
import { eventBus } from '../core/EventBus';
import { calendarConfig } from '../core/CalendarConfig';
import { CoreEvents } from '../constants/CoreEvents';
import { ResourceCalendarData, CalendarView } from '../types/CalendarTypes';
import { AllDayEvent } from '../types/EventTypes';
import { ViewStrategy, ViewContext } from '../strategies/ViewStrategy';
import { WeekViewStrategy } from '../strategies/WeekViewStrategy';
import { MonthViewStrategy } from '../strategies/MonthViewStrategy';
/**
* Simplified GridManager focused on coordination, not implementation
*/
export class GridManager {
private container: HTMLElement | null = null;
private currentDate: Date = new Date();
private allDayEvents: AllDayEvent[] = [];
private resourceData: ResourceCalendarData | null = null;
private currentStrategy: ViewStrategy;
private eventCleanup: (() => void)[] = [];
constructor() {
console.log('🏗️ GridManager: Constructor called with Strategy Pattern');
// Default to week view strategy
this.currentStrategy = new WeekViewStrategy();
this.init();
}
private init(): void {
this.findElements();
this.subscribeToEvents();
2025-07-25 23:31:25 +02:00
console.log('GridManager: Initialized with strategy pattern');
}
private findElements(): void {
this.container = document.querySelector('swp-calendar-container');
console.log('GridManager: Found container:', !!this.container);
}
private subscribeToEvents(): void {
// Listen for view changes to switch strategies
this.eventCleanup.push(
eventBus.on(CoreEvents.VIEW_CHANGED, (e: Event) => {
const detail = (e as CustomEvent).detail;
this.switchViewStrategy(detail.currentView);
})
);
// Listen for data changes
// REMOVED: GridManager should not re-render on DATE_CHANGED
// Date navigation is handled by NavigationManager
// this.eventCleanup.push(
// eventBus.on(CoreEvents.DATE_CHANGED, (e: Event) => {
// const detail = (e as CustomEvent).detail;
// this.currentDate = detail.currentDate;
// this.render();
// })
// );
// REMOVED: GridManager should not re-render on WEEK_CHANGED
// Navigation is handled by NavigationManager + NavigationRenderer
// this.eventCleanup.push(
// eventBus.on(CoreEvents.WEEK_CHANGED, (e: Event) => {
// const detail = (e as CustomEvent).detail;
// this.currentDate = detail.weekStart;
// this.render();
// })
// );
this.eventCleanup.push(
eventBus.on(CoreEvents.DATA_LOADED, (e: Event) => {
const detail = (e as CustomEvent).detail;
this.updateAllDayEvents(detail.events);
})
);
// Listen for config changes that affect rendering
this.eventCleanup.push(
eventBus.on(CoreEvents.REFRESH_REQUESTED, (e: Event) => {
this.render();
})
);
this.eventCleanup.push(
eventBus.on(CoreEvents.WORKWEEK_CHANGED, () => {
this.render();
})
);
}
/**
* Switch to a different view strategy
*/
public switchViewStrategy(view: CalendarView): void {
console.log(`GridManager: Switching to ${view} strategy`);
// Clean up current strategy
this.currentStrategy.destroy();
// Create new strategy based on view
switch (view) {
case 'week':
case 'day':
this.currentStrategy = new WeekViewStrategy();
break;
case 'month':
this.currentStrategy = new MonthViewStrategy();
break;
default:
console.warn(`GridManager: Unknown view type ${view}, defaulting to week`);
this.currentStrategy = new WeekViewStrategy();
}
// Re-render with new strategy
this.render();
}
/**
* Set resource data for resource calendar mode
*/
public setResourceData(resourceData: ResourceCalendarData | null): void {
this.resourceData = resourceData;
console.log('GridManager: Updated resource data');
this.render();
}
/**
* Main render method - delegates to current strategy
*/
public async render(): Promise<void> {
if (!this.container) {
console.warn('GridManager: No container found, cannot render');
return;
2025-08-09 01:16:04 +02:00
}
console.log(`🎨 GridManager: Rendering ${this.currentDate.toDateString()} using ${this.currentStrategy.constructor.name}`);
// Create context for strategy
const context: ViewContext = {
currentDate: this.currentDate,
container: this.container,
allDayEvents: this.allDayEvents,
resourceData: this.resourceData
};
// Delegate to current strategy
this.currentStrategy.renderGrid(context);
// Get layout info from strategy
const layoutConfig = this.currentStrategy.getLayoutConfig();
console.log(`GridManager: Emitting GRID_RENDERED for main container`);
// Emit grid rendered event
eventBus.emit(CoreEvents.GRID_RENDERED, {
container: this.container,
currentDate: this.currentDate,
layoutConfig: layoutConfig,
columnCount: layoutConfig.columnCount
});
console.log(`✅ Grid rendered with ${layoutConfig.columnCount} columns`);
}
2025-08-04 23:55:04 +02:00
/**
* Update all-day events and re-render
2025-08-04 23:55:04 +02:00
*/
private updateAllDayEvents(events: AllDayEvent[]): void {
console.log(`GridManager: Updating ${events.length} all-day events`);
this.allDayEvents = events.filter(event => event.allDay);
this.render();
2025-08-04 23:55:04 +02:00
}
/**
* Get current period label from strategy
*/
public getCurrentPeriodLabel(): string {
return this.currentStrategy.getPeriodLabel(this.currentDate);
}
/**
* Navigate to next period using strategy
*/
public navigateNext(): void {
const nextDate = this.currentStrategy.getNextPeriod(this.currentDate);
this.currentDate = nextDate;
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
direction: 'next',
newDate: nextDate,
periodLabel: this.getCurrentPeriodLabel()
});
this.render();
}
/**
* Navigate to previous period using strategy
*/
public navigatePrevious(): void {
const prevDate = this.currentStrategy.getPreviousPeriod(this.currentDate);
this.currentDate = prevDate;
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
direction: 'previous',
newDate: prevDate,
periodLabel: this.getCurrentPeriodLabel()
});
this.render();
}
2025-07-25 23:31:25 +02:00
/**
* Navigate to today
2025-07-25 23:31:25 +02:00
*/
public navigateToToday(): void {
this.currentDate = new Date();
2025-07-25 23:31:25 +02:00
eventBus.emit(CoreEvents.DATE_CHANGED, {
newDate: this.currentDate,
periodLabel: this.getCurrentPeriodLabel()
});
2025-07-25 23:31:25 +02:00
this.render();
2025-07-25 23:31:25 +02:00
}
/**
* Get current view's display dates
*/
public getDisplayDates(): Date[] {
return this.currentStrategy.getDisplayDates(this.currentDate);
}
/**
* Clean up all resources
*/
public destroy(): void {
console.log('GridManager: Cleaning up');
// Clean up event listeners
this.eventCleanup.forEach(cleanup => cleanup());
this.eventCleanup = [];
// Clean up current strategy
this.currentStrategy.destroy();
// Clear references
this.container = null;
this.allDayEvents = [];
this.resourceData = null;
}
}