Refactors calendar architecture for month view

Prepares the calendar component for month view implementation
by introducing a strategy pattern for view management,
splitting configuration settings, and consolidating events
into a core set. It also removes dead code and enforces type safety,
improving overall code quality and maintainability.

Addresses critical issues identified in the code review,
laying the groundwork for efficient feature addition.
This commit is contained in:
Janus Knudsen 2025-08-20 19:42:13 +02:00
parent 7d513600d8
commit 3ddc6352f2
17 changed files with 1347 additions and 428 deletions

View file

@ -10,6 +10,8 @@ import { EventTypes } from '../constants/EventTypes';
export class ViewManager {
private eventBus: IEventBus;
private currentView: CalendarView = 'week';
private eventCleanup: (() => void)[] = [];
private buttonListeners: Map<Element, EventListener> = new Map();
constructor(eventBus: IEventBus) {
this.eventBus = eventBus;
@ -17,19 +19,26 @@ export class ViewManager {
}
private setupEventListeners(): void {
this.eventBus.on(EventTypes.CALENDAR_INITIALIZED, () => {
this.initializeView();
});
// Track event bus listeners for cleanup
this.eventCleanup.push(
this.eventBus.on(EventTypes.CALENDAR_INITIALIZED, () => {
this.initializeView();
})
);
this.eventBus.on(EventTypes.VIEW_CHANGE_REQUESTED, (event: Event) => {
const customEvent = event as CustomEvent;
const { currentView } = customEvent.detail;
this.changeView(currentView);
});
this.eventCleanup.push(
this.eventBus.on(EventTypes.VIEW_CHANGE_REQUESTED, (event: Event) => {
const customEvent = event as CustomEvent;
const { currentView } = customEvent.detail;
this.changeView(currentView);
})
);
this.eventBus.on(EventTypes.DATE_CHANGED, () => {
this.refreshCurrentView();
});
this.eventCleanup.push(
this.eventBus.on(EventTypes.DATE_CHANGED, () => {
this.refreshCurrentView();
})
);
// Setup view button handlers
this.setupViewButtonHandlers();
@ -42,26 +51,30 @@ export class ViewManager {
private setupViewButtonHandlers(): void {
const viewButtons = document.querySelectorAll('swp-view-button[data-view]');
viewButtons.forEach(button => {
button.addEventListener('click', (event) => {
const handler = (event: Event) => {
event.preventDefault();
const view = button.getAttribute('data-view') as CalendarView;
if (view && this.isValidView(view)) {
this.changeView(view);
}
});
};
button.addEventListener('click', handler);
this.buttonListeners.set(button, handler);
});
}
private setupWorkweekButtonHandlers(): void {
const workweekButtons = document.querySelectorAll('swp-preset-button[data-workweek]');
workweekButtons.forEach(button => {
button.addEventListener('click', (event) => {
const handler = (event: Event) => {
event.preventDefault();
const workweekId = button.getAttribute('data-workweek');
if (workweekId) {
this.changeWorkweek(workweekId);
}
});
};
button.addEventListener('click', handler);
this.buttonListeners.set(button, handler);
});
}
@ -149,6 +162,14 @@ export class ViewManager {
}
public destroy(): void {
// Event listeners bliver automatisk fjernet af EventBus
// Clean up event bus listeners
this.eventCleanup.forEach(cleanup => cleanup());
this.eventCleanup = [];
// Clean up button listeners
this.buttonListeners.forEach((handler, button) => {
button.removeEventListener('click', handler);
});
this.buttonListeners.clear();
}
}