import { IEventBus } from '../types/CalendarTypes';
import { EventTypes } from '../constants/EventTypes';
import { DateUtils } from '../utils/DateUtils';
import { CalendarConfig } from '../core/CalendarConfig';
/**
* NavigationRenderer - Handles DOM rendering for navigation containers
* Separated from NavigationManager to follow Single Responsibility Principle
*/
export class NavigationRenderer {
private eventBus: IEventBus;
private config: CalendarConfig;
constructor(eventBus: IEventBus, config: CalendarConfig) {
this.eventBus = eventBus;
this.config = config;
this.setupEventListeners();
}
/**
* Setup event listeners for DOM updates
*/
private setupEventListeners(): void {
this.eventBus.on(EventTypes.WEEK_INFO_UPDATED, (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;
}
}
/**
* Render a complete container with content and events
*/
public renderContainer(parentContainer: HTMLElement, weekStart: Date): HTMLElement {
console.log('NavigationRenderer: Rendering new container for week:', weekStart.toDateString());
// 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);
// Render week content (headers and columns)
this.renderWeekContentInContainer(newGrid, weekStart);
// Emit event to trigger event rendering
const weekEnd = DateUtils.addDays(weekStart, 6);
this.eventBus.emit(EventTypes.CONTAINER_READY_FOR_EVENTS, {
container: newGrid,
startDate: weekStart,
endDate: weekEnd
});
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 = '';
// Render headers for target week
const workWeekSettings = this.config.getWorkWeekSettings();
workWeekSettings.workDays.forEach((dayOfWeek, i) => {
const date = new Date(weekStart);
// Set to the start of the week (Sunday = 0)
date.setDate(weekStart.getDate() - weekStart.getDay());
// Add the specific day of week
date.setDate(date.getDate() + dayOfWeek);
const headerElement = document.createElement('swp-day-header');
if (this.isToday(date)) {
headerElement.dataset.today = 'true';
}
headerElement.innerHTML = `
${workWeekSettings.dayNames[i]}
${date.getDate()}
`;
headerElement.dataset.date = this.formatDate(date);
header.appendChild(headerElement);
});
// Render day columns for target week
workWeekSettings.workDays.forEach(dayOfWeek => {
const column = document.createElement('swp-day-column');
const date = new Date(weekStart);
// Set to the start of the week (Sunday = 0)
date.setDate(weekStart.getDate() - weekStart.getDay());
// Add the specific day of week
date.setDate(date.getDate() + dayOfWeek);
column.dataset.date = this.formatDate(date);
const eventsLayer = document.createElement('swp-events-layer');
column.appendChild(eventsLayer);
dayColumns.appendChild(column);
});
}
/**
* Utility method to format date
*/
private formatDate(date: Date): string {
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}
/**
* Check if date is today
*/
private isToday(date: Date): boolean {
const today = new Date();
return date.toDateString() === today.toDateString();
}
}