Calendar/src/renderers/NavigationRenderer.ts
Janus Knudsen fafad16926 Removes excessive logging statements
Cleans up the codebase by removing unnecessary console log statements.

These logs were primarily used for debugging and are no longer needed in the production code.
This reduces noise in the console and improves overall performance.
2025-08-31 22:39:09 +02:00

238 lines
No EOL
8.2 KiB
TypeScript

import { IEventBus } from '../types/CalendarTypes';
import { CoreEvents } from '../constants/CoreEvents';
import { CalendarConfig } from '../core/CalendarConfig';
import { DateCalculator } from '../utils/DateCalculator';
import { EventRenderingService } from './EventRendererManager';
import { CalendarTypeFactory } from '../factories/CalendarTypeFactory';
import { eventBus } from '../core/EventBus';
/**
* 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);
// 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);
this.renderWeekContentInContainer(newGrid, weekStart);
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
});
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 = `
<swp-day-name>${dayName}</swp-day-name>
<swp-day-date>${date.getDate()}</swp-day-date>
`;
headerElement.dataset.date = this.dateCalculator.formatISODate(date);
header.appendChild(headerElement);
});
// Always ensure all-day containers exist for all days
const headerRenderer = CalendarTypeFactory.getHeaderRenderer(this.config.getCalendarMode());
headerRenderer.ensureAllDayContainers(header as HTMLElement);
// Add event delegation listener for drag & drop functionality
this.setupHeaderEventListener(header as HTMLElement);
// 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);
});
}
/**
* Setup event delegation listener for header mouseover (same logic as GridRenderer)
*/
private setupHeaderEventListener(calendarHeader: HTMLElement): void {
calendarHeader.addEventListener('mouseover', (event) => {
const target = event.target as HTMLElement;
// Check what was hovered - could be day-header OR all-day-container
const dayHeader = target.closest('swp-day-header');
const allDayContainer = target.closest('swp-allday-container');
if (dayHeader || allDayContainer) {
let hoveredElement: HTMLElement;
let targetDate: string | undefined;
if (dayHeader) {
hoveredElement = dayHeader as HTMLElement;
targetDate = hoveredElement.dataset.date;
} else if (allDayContainer) {
// For all-day areas, we need to determine which day column we're over
hoveredElement = allDayContainer as HTMLElement;
// Calculate which day we're hovering over based on mouse position
const headerRect = calendarHeader.getBoundingClientRect();
const dayHeaders = calendarHeader.querySelectorAll('swp-day-header');
const mouseX = (event as MouseEvent).clientX - headerRect.left;
const dayWidth = headerRect.width / dayHeaders.length;
const dayIndex = Math.floor(mouseX / dayWidth);
const targetDayHeader = dayHeaders[dayIndex] as HTMLElement;
targetDate = targetDayHeader?.dataset.date;
} else {
return; // No valid element found
}
// Get the header renderer for addToAllDay functionality
const calendarType = this.config.getCalendarMode();
const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType);
eventBus.emit('header:mouseover', {
element: hoveredElement,
targetDate,
headerRenderer
});
}
});
}
}