/** * 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 { 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 resourceData: ResourceCalendarData | null = null; private currentStrategy: ViewStrategy; private eventCleanup: (() => void)[] = []; constructor() { // Default to week view strategy this.currentStrategy = new WeekViewStrategy(); this.init(); } private init(): void { this.findElements(); this.subscribeToEvents(); } private findElements(): void { this.container = document.querySelector('swp-calendar-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 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 { // 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: 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; this.render(); } /** * Main render method - delegates to current strategy */ public async render(): Promise { if (!this.container) { return; } // Create context for strategy const context: ViewContext = { currentDate: this.currentDate, container: this.container, resourceData: this.resourceData }; // Delegate to current strategy this.currentStrategy.renderGrid(context); // Get layout info from strategy const layoutConfig = this.currentStrategy.getLayoutConfig(); // Get period range from current strategy const periodRange = this.currentStrategy.getPeriodRange(this.currentDate); // Emit grid rendered event with explicit date range eventBus.emit(CoreEvents.GRID_RENDERED, { container: this.container, currentDate: this.currentDate, startDate: periodRange.startDate, endDate: periodRange.endDate, layoutConfig: layoutConfig, columnCount: layoutConfig.columnCount }); } /** * 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(); } /** * Navigate to today */ public navigateToToday(): void { this.currentDate = new Date(); eventBus.emit(CoreEvents.DATE_CHANGED, { newDate: this.currentDate, periodLabel: this.getCurrentPeriodLabel() }); this.render(); } /** * Get current view's display dates */ public getDisplayDates(): Date[] { return this.currentStrategy.getDisplayDates(this.currentDate); } /** * Clean up all resources */ public destroy(): void { // Clean up event listeners this.eventCleanup.forEach(cleanup => cleanup()); this.eventCleanup = []; // Clean up current strategy this.currentStrategy.destroy(); // Clear references this.container = null; this.resourceData = null; } }