2025-08-17 22:54:00 +02:00
|
|
|
import { IEventBus } from '../types/CalendarTypes';
|
|
|
|
|
import { EventTypes } from '../constants/EventTypes';
|
|
|
|
|
import { DateUtils } from '../utils/DateUtils';
|
2025-08-18 22:27:17 +02:00
|
|
|
import { CalendarConfig } from '../core/CalendarConfig';
|
2025-08-18 23:42:03 +02:00
|
|
|
import { DateCalculator } from '../utils/DateCalculator';
|
2025-08-17 22:54:00 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* NavigationRenderer - Handles DOM rendering for navigation containers
|
|
|
|
|
* Separated from NavigationManager to follow Single Responsibility Principle
|
|
|
|
|
*/
|
|
|
|
|
export class NavigationRenderer {
|
|
|
|
|
private eventBus: IEventBus;
|
2025-08-18 22:27:17 +02:00
|
|
|
private config: CalendarConfig;
|
2025-08-18 23:42:03 +02:00
|
|
|
private dateCalculator: DateCalculator;
|
2025-08-17 22:54:00 +02:00
|
|
|
|
2025-08-18 22:27:17 +02:00
|
|
|
constructor(eventBus: IEventBus, config: CalendarConfig) {
|
2025-08-17 22:54:00 +02:00
|
|
|
this.eventBus = eventBus;
|
2025-08-18 22:27:17 +02:00
|
|
|
this.config = config;
|
2025-08-18 23:42:03 +02:00
|
|
|
this.dateCalculator = new DateCalculator(config);
|
2025-08-17 23:44:30 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2025-08-17 22:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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 = `
|
|
|
|
|
<swp-calendar-header></swp-calendar-header>
|
|
|
|
|
<swp-scrollable-content>
|
|
|
|
|
<swp-time-grid>
|
|
|
|
|
<swp-grid-lines></swp-grid-lines>
|
|
|
|
|
<swp-day-columns></swp-day-columns>
|
|
|
|
|
</swp-time-grid>
|
|
|
|
|
</swp-scrollable-content>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
// 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 = '';
|
|
|
|
|
|
2025-08-18 23:42:03 +02:00
|
|
|
// Get dates using DateCalculator
|
|
|
|
|
const dates = this.dateCalculator.getWorkWeekDates(weekStart);
|
2025-08-18 22:27:17 +02:00
|
|
|
const workWeekSettings = this.config.getWorkWeekSettings();
|
2025-08-18 23:42:03 +02:00
|
|
|
|
|
|
|
|
// Render headers for target week
|
|
|
|
|
dates.forEach((date, i) => {
|
2025-08-17 22:54:00 +02:00
|
|
|
const headerElement = document.createElement('swp-day-header');
|
2025-08-18 23:42:03 +02:00
|
|
|
if (this.dateCalculator.isToday(date)) {
|
2025-08-17 22:54:00 +02:00
|
|
|
headerElement.dataset.today = 'true';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
headerElement.innerHTML = `
|
2025-08-18 22:27:17 +02:00
|
|
|
<swp-day-name>${workWeekSettings.dayNames[i]}</swp-day-name>
|
2025-08-17 22:54:00 +02:00
|
|
|
<swp-day-date>${date.getDate()}</swp-day-date>
|
|
|
|
|
`;
|
2025-08-18 23:42:03 +02:00
|
|
|
headerElement.dataset.date = this.dateCalculator.formatISODate(date);
|
2025-08-17 22:54:00 +02:00
|
|
|
|
|
|
|
|
header.appendChild(headerElement);
|
2025-08-18 22:27:17 +02:00
|
|
|
});
|
2025-08-17 22:54:00 +02:00
|
|
|
|
|
|
|
|
// Render day columns for target week
|
2025-08-18 23:42:03 +02:00
|
|
|
dates.forEach(date => {
|
2025-08-17 22:54:00 +02:00
|
|
|
const column = document.createElement('swp-day-column');
|
2025-08-18 23:42:03 +02:00
|
|
|
column.dataset.date = this.dateCalculator.formatISODate(date);
|
2025-08-17 22:54:00 +02:00
|
|
|
|
|
|
|
|
const eventsLayer = document.createElement('swp-events-layer');
|
|
|
|
|
column.appendChild(eventsLayer);
|
|
|
|
|
|
|
|
|
|
dayColumns.appendChild(column);
|
2025-08-18 22:27:17 +02:00
|
|
|
});
|
2025-08-17 22:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|