import { eventBus } from '../core/EventBus'; import { CalendarConfig } from '../core/CalendarConfig'; import { CoreEvents } from '../constants/CoreEvents'; import { IHeaderRenderer, HeaderRenderContext } from '../renderers/DateHeaderRenderer'; import { DragMouseEnterHeaderEventPayload, DragMouseLeaveHeaderEventPayload, HeaderReadyEventPayload } from '../types/EventTypes'; import { ColumnDetectionUtils } from '../utils/ColumnDetectionUtils'; /** * HeaderManager - Handles all header-related event logic * Separates event handling from rendering concerns * Uses dependency injection for renderer strategy */ export class HeaderManager { private headerRenderer: IHeaderRenderer; private config: CalendarConfig; constructor(headerRenderer: IHeaderRenderer, config: CalendarConfig) { this.headerRenderer = headerRenderer; this.config = config; // Bind handler methods for event listeners this.handleDragMouseEnterHeader = this.handleDragMouseEnterHeader.bind(this); this.handleDragMouseLeaveHeader = this.handleDragMouseLeaveHeader.bind(this); // Listen for navigation events to update header this.setupNavigationListener(); } /** * Setup header drag event listeners - Listen to DragDropManager events */ public setupHeaderDragListeners(): void { console.log('🎯 HeaderManager: Setting up drag event listeners'); // Subscribe to drag events from DragDropManager eventBus.on('drag:mouseenter-header', this.handleDragMouseEnterHeader); eventBus.on('drag:mouseleave-header', this.handleDragMouseLeaveHeader); console.log('✅ HeaderManager: Drag event listeners attached'); } /** * Handle drag mouse enter header event */ private handleDragMouseEnterHeader(event: Event): void { const { targetColumn: targetDate, mousePosition, originalElement, draggedClone: cloneElement } = (event as CustomEvent).detail; console.log('🎯 HeaderManager: Received drag:mouseenter-header', { targetDate, originalElement: !!originalElement, cloneElement: !!cloneElement }); } /** * Handle drag mouse leave header event */ private handleDragMouseLeaveHeader(event: Event): void { const { targetDate, mousePosition, originalElement, draggedClone: cloneElement } = (event as CustomEvent).detail; console.log('🚪 HeaderManager: Received drag:mouseleave-header', { targetDate, originalElement: !!originalElement, cloneElement: !!cloneElement }); } /** * Setup navigation event listener */ private setupNavigationListener(): void { eventBus.on(CoreEvents.NAVIGATION_COMPLETED, (event) => { const { currentDate } = (event as CustomEvent).detail; this.updateHeader(currentDate); }); // Also listen for date changes (including initial setup) eventBus.on(CoreEvents.DATE_CHANGED, (event) => { const { currentDate } = (event as CustomEvent).detail; this.updateHeader(currentDate); }); // Listen for workweek header updates after grid rebuild eventBus.on('workweek:header-update', (event) => { const { currentDate } = (event as CustomEvent).detail; this.updateHeader(currentDate); }); } /** * Update header content for navigation */ private updateHeader(currentDate: Date): void { console.log('🎯 HeaderManager.updateHeader called', { currentDate, rendererType: this.headerRenderer.constructor.name }); const calendarHeader = document.querySelector('swp-calendar-header') as HTMLElement; if (!calendarHeader) { console.warn('❌ HeaderManager: No calendar header found!'); return; } // Clear existing content calendarHeader.innerHTML = ''; // Render new header content using injected renderer const context: HeaderRenderContext = { currentWeek: currentDate, config: this.config }; this.headerRenderer.render(calendarHeader, context); // Setup event listeners on the new content this.setupHeaderDragListeners(); // Notify other managers that header is ready with period data const payload: HeaderReadyEventPayload = { headerElements: ColumnDetectionUtils.getHeaderColumns(), }; eventBus.emit('header:ready', payload); } }