import { IEventBus } from '../types/CalendarTypes'; import { CoreEvents } from '../constants/CoreEvents'; import { CalendarConfig } from '../core/CalendarConfig'; import { DateCalculator } from '../utils/DateCalculator'; import { EventRenderingService } from './EventRendererManager'; /** * NavigationRenderer - Handles DOM rendering for navigation containers * Separated from NavigationManager to follow Single Responsibility Principle */ export class NavigationRenderer { private eventBus: IEventBus; private config: CalendarConfig; private dateCalculator: DateCalculator; private eventRenderer: EventRenderingService; constructor(eventBus: IEventBus, config: CalendarConfig, eventRenderer: EventRenderingService) { this.eventBus = eventBus; this.config = config; this.eventRenderer = eventRenderer; this.dateCalculator = new DateCalculator(config); this.setupEventListeners(); } /** * Setup event listeners for DOM updates */ private setupEventListeners(): void { this.eventBus.on(CoreEvents.WEEK_CHANGED, (event: Event) => { const customEvent = event as CustomEvent; const { weekNumber, dateRange } = customEvent.detail; this.updateWeekInfoInDOM(weekNumber, dateRange); }); } /** * Update week info in DOM elements */ private updateWeekInfoInDOM(weekNumber: number, dateRange: string): void { const weekNumberElement = document.querySelector('swp-week-number'); const dateRangeElement = document.querySelector('swp-date-range'); if (weekNumberElement) { weekNumberElement.textContent = `Week ${weekNumber}`; } if (dateRangeElement) { dateRangeElement.textContent = dateRange; } } /** * Apply filter state to pre-rendered grids */ public applyFilterToPreRenderedGrids(filterState: { active: boolean; matchingIds: string[] }): void { // Find all grid containers (including pre-rendered ones) const allGridContainers = document.querySelectorAll('swp-grid-container'); allGridContainers.forEach(container => { const eventsLayers = container.querySelectorAll('swp-events-layer'); eventsLayers.forEach(layer => { if (filterState.active) { // Apply filter active state layer.setAttribute('data-filter-active', 'true'); // Mark matching events in this layer const events = layer.querySelectorAll('swp-event'); events.forEach(event => { const eventId = event.getAttribute('data-event-id'); if (eventId && filterState.matchingIds.includes(eventId)) { event.setAttribute('data-matches', 'true'); } else { event.removeAttribute('data-matches'); } }); } else { // Remove filter state layer.removeAttribute('data-filter-active'); // Remove all match attributes const events = layer.querySelectorAll('swp-event'); events.forEach(event => { event.removeAttribute('data-matches'); }); } }); }); } /** * Render a complete container with content and events */ public renderContainer(parentContainer: HTMLElement, weekStart: Date): HTMLElement { const weekEnd = this.dateCalculator.addDays(weekStart, 6); console.group(`🎨 RENDERING CONTAINER: ${weekStart.toDateString()} - ${weekEnd.toDateString()}`); console.log('1. Creating grid structure...'); // Create new grid container const newGrid = document.createElement('swp-grid-container'); newGrid.innerHTML = ` `; // Position new grid - NO transform here, let Animation API handle it newGrid.style.position = 'absolute'; newGrid.style.top = '0'; newGrid.style.left = '0'; newGrid.style.width = '100%'; newGrid.style.height = '100%'; // Add to parent container parentContainer.appendChild(newGrid); console.log('2. Rendering headers and columns...'); this.renderWeekContentInContainer(newGrid, weekStart); console.log('3. Emitting GRID_RENDERED for navigation container...'); this.eventBus.emit(CoreEvents.GRID_RENDERED, { container: newGrid, // Specific grid container, not parent currentDate: weekStart, startDate: weekStart, endDate: weekEnd, isNavigation: true // Flag to indicate this is navigation rendering }); console.log('✅ Container ready with GRID_RENDERED event emitted'); console.groupEnd(); return newGrid; } /** * Render week content in specific container */ private renderWeekContentInContainer(gridContainer: HTMLElement, weekStart: Date): void { const header = gridContainer.querySelector('swp-calendar-header'); const dayColumns = gridContainer.querySelector('swp-day-columns'); if (!header || !dayColumns) return; // Clear existing content header.innerHTML = ''; dayColumns.innerHTML = ''; // Get dates using DateCalculator const dates = this.dateCalculator.getWorkWeekDates(weekStart); // Render headers for target week dates.forEach((date, i) => { const headerElement = document.createElement('swp-day-header'); if (this.dateCalculator.isToday(date)) { headerElement.dataset.today = 'true'; } const dayName = this.dateCalculator.getDayName(date, 'short'); headerElement.innerHTML = ` ${dayName} ${date.getDate()} `; headerElement.dataset.date = this.dateCalculator.formatISODate(date); header.appendChild(headerElement); }); // Render day columns for target week dates.forEach(date => { const column = document.createElement('swp-day-column'); column.dataset.date = this.dateCalculator.formatISODate(date); const eventsLayer = document.createElement('swp-events-layer'); column.appendChild(eventsLayer); dayColumns.appendChild(column); }); } }