import { eventBus } from '../core/EventBus'; import { calendarConfig } from '../core/CalendarConfig'; import { CoreEvents } from '../constants/CoreEvents'; import { HeaderRenderer, HeaderRenderContext } from '../renderers/HeaderRenderer'; import { ResourceCalendarData } from '../types/CalendarTypes'; 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: HeaderRenderer; constructor(headerRenderer: HeaderRenderer) { this.headerRenderer = headerRenderer; // 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(); } /** * Initialize header with initial date */ public initializeHeader(currentDate: Date, resourceData: ResourceCalendarData | null = null): void { this.updateHeader(currentDate, resourceData); } /** * Get cached calendar header element */ private getCalendarHeader(): HTMLElement | null { return document.querySelector('swp-calendar-header'); } /** * 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 }); // Header renderer already injected - ready to use if needed } /** * 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, resourceData } = (event as CustomEvent).detail; this.updateHeader(currentDate, resourceData); }); // Also listen for date changes (including initial setup) eventBus.on(CoreEvents.DATE_CHANGED, (event) => { const { currentDate } = (event as CustomEvent).detail; this.updateHeader(currentDate, null); }); // Listen for workweek header updates after grid rebuild eventBus.on('workweek:header-update', (event) => { const { currentDate } = (event as CustomEvent).detail; this.updateHeader(currentDate, null); }); } /** * Update header content for navigation */ private updateHeader(currentDate: Date, resourceData: ResourceCalendarData | null = null): void { console.log('🎯 HeaderManager.updateHeader called', { currentDate, hasResourceData: !!resourceData, rendererType: this.headerRenderer.constructor.name }); const calendarHeader = this.getOrCreateCalendarHeader(); 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: calendarConfig, resourceData: resourceData }; console.log('🎨 HeaderManager: Calling renderer.render()', context); this.headerRenderer.render(calendarHeader, context); console.log('✅ HeaderManager: Renderer completed'); // 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); } /** * Get calendar header element - header always exists now */ private getOrCreateCalendarHeader(): HTMLElement | null { const calendarHeader = this.getCalendarHeader(); if (!calendarHeader) { console.warn('HeaderManager: Calendar header not found - should always exist now!'); return null; } return calendarHeader; } }