import { CalendarConfig } from '../core/CalendarConfig'; import { ResourceCalendarData } from '../types/CalendarTypes'; import { CalendarTypeFactory } from '../factories/CalendarTypeFactory'; import { HeaderRenderContext } from './HeaderRenderer'; import { ColumnRenderContext } from './ColumnRenderer'; /** * GridRenderer - Handles DOM rendering for the calendar grid * Separated from GridManager to follow Single Responsibility Principle */ export class GridRenderer { private config: CalendarConfig; constructor(config: CalendarConfig) { this.config = config; } /** * Render the complete grid structure */ public renderGrid( grid: HTMLElement, currentWeek: Date, resourceData: ResourceCalendarData | null, allDayEvents: any[] ): void { console.log('GridRenderer: renderGrid called', { hasGrid: !!grid, hasCurrentWeek: !!currentWeek, currentWeek: currentWeek }); if (!grid || !currentWeek) { console.warn('GridRenderer: Cannot render - missing grid or currentWeek'); return; } // Only clear and rebuild if grid is empty (first render) if (grid.children.length === 0) { console.log('GridRenderer: First render - creating grid structure'); // Create POC structure: header-spacer + time-axis + grid-container this.createHeaderSpacer(grid); this.createTimeAxis(grid); this.createGridContainer(grid, currentWeek, resourceData, allDayEvents); } else { console.log('GridRenderer: Re-render - updating existing structure'); // Just update the calendar header for all-day events this.updateCalendarHeader(grid, currentWeek, resourceData, allDayEvents); } console.log('GridRenderer: Grid rendered successfully with POC structure'); } /** * Create header spacer to align time axis with week content */ private createHeaderSpacer(grid: HTMLElement): void { const headerSpacer = document.createElement('swp-header-spacer'); grid.appendChild(headerSpacer); } /** * Create time axis (positioned beside grid container) */ private createTimeAxis(grid: HTMLElement): void { const timeAxis = document.createElement('swp-time-axis'); const timeAxisContent = document.createElement('swp-time-axis-content'); const gridSettings = this.config.getGridSettings(); const startHour = gridSettings.dayStartHour; const endHour = gridSettings.dayEndHour; console.log('GridRenderer: Creating time axis - startHour:', startHour, 'endHour:', endHour); for (let hour = startHour; hour < endHour; hour++) { const marker = document.createElement('swp-hour-marker'); const period = hour >= 12 ? 'PM' : 'AM'; const displayHour = hour > 12 ? hour - 12 : (hour === 0 ? 12 : hour); marker.textContent = `${displayHour} ${period}`; timeAxisContent.appendChild(marker); } timeAxis.appendChild(timeAxisContent); grid.appendChild(timeAxis); } /** * Create grid container with header and scrollable content */ private createGridContainer( grid: HTMLElement, currentWeek: Date, resourceData: ResourceCalendarData | null, allDayEvents: any[] ): void { const gridContainer = document.createElement('swp-grid-container'); // Create calendar header using Strategy Pattern const calendarHeader = document.createElement('swp-calendar-header'); this.renderCalendarHeader(calendarHeader, currentWeek, resourceData, allDayEvents); gridContainer.appendChild(calendarHeader); // Create scrollable content const scrollableContent = document.createElement('swp-scrollable-content'); const timeGrid = document.createElement('swp-time-grid'); // Add grid lines const gridLines = document.createElement('swp-grid-lines'); timeGrid.appendChild(gridLines); // Create column container using Strategy Pattern const columnContainer = document.createElement('swp-day-columns'); this.renderColumnContainer(columnContainer, currentWeek, resourceData); timeGrid.appendChild(columnContainer); scrollableContent.appendChild(timeGrid); gridContainer.appendChild(scrollableContent); grid.appendChild(gridContainer); } /** * Render calendar header using Strategy Pattern */ private renderCalendarHeader( calendarHeader: HTMLElement, currentWeek: Date, resourceData: ResourceCalendarData | null, allDayEvents: any[] ): void { const calendarType = this.config.getCalendarMode(); const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType); const context: HeaderRenderContext = { currentWeek: currentWeek, config: this.config, allDayEvents: allDayEvents, resourceData: resourceData }; headerRenderer.render(calendarHeader, context); } /** * Render column container using Strategy Pattern */ private renderColumnContainer( columnContainer: HTMLElement, currentWeek: Date, resourceData: ResourceCalendarData | null ): void { console.log('GridRenderer: renderColumnContainer called'); const calendarType = this.config.getCalendarMode(); const columnRenderer = CalendarTypeFactory.getColumnRenderer(calendarType); const context: ColumnRenderContext = { currentWeek: currentWeek, config: this.config, resourceData: resourceData }; columnRenderer.render(columnContainer, context); } /** * Update only the calendar header without rebuilding entire grid */ private updateCalendarHeader( grid: HTMLElement, currentWeek: Date, resourceData: ResourceCalendarData | null, allDayEvents: any[] ): void { const calendarHeader = grid.querySelector('swp-calendar-header'); if (!calendarHeader) return; // Clear existing content calendarHeader.innerHTML = ''; // Re-render headers using Strategy Pattern this.renderCalendarHeader(calendarHeader as HTMLElement, currentWeek, resourceData, allDayEvents); } }