/** * 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 { EventTypes } from '../constants/EventTypes'; 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(); 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(EventTypes.VIEW_CHANGED, (e: Event) => { const detail = (e as CustomEvent).detail; this.switchViewStrategy(detail.currentView); }) ); // Listen for data changes this.eventCleanup.push( eventBus.on(EventTypes.DATE_CHANGED, (e: Event) => { const detail = (e as CustomEvent).detail; this.currentDate = detail.currentDate; this.render(); }) ); this.eventCleanup.push( eventBus.on(EventTypes.WEEK_CHANGED, (e: Event) => { const detail = (e as CustomEvent).detail; this.currentDate = detail.weekStart; this.render(); }) ); this.eventCleanup.push( eventBus.on(EventTypes.EVENTS_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(EventTypes.CONFIG_UPDATE, (e: Event) => { this.render(); }) ); this.eventCleanup.push( eventBus.on(EventTypes.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 { if (!this.container) { console.warn('GridManager: No container found, cannot render'); return; } console.group(`🎨 GRID RENDER: ${this.currentDate.toDateString()}`); console.log(`Using strategy: ${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(); // 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`); console.groupEnd(); } /** * Update all-day events and re-render */ private updateAllDayEvents(events: AllDayEvent[]): void { console.log(`GridManager: Updating ${events.length} all-day events`); this.allDayEvents = events.filter(event => event.allDay); this.render(); } /** * 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 { 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; } }