2025-08-20 19:52:18 +02:00
|
|
|
/**
|
|
|
|
|
* GridManager - Simplified grid manager using Strategy Pattern
|
|
|
|
|
* Now delegates view-specific logic to strategy implementations
|
|
|
|
|
*/
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
import { eventBus } from '../core/EventBus';
|
|
|
|
|
import { calendarConfig } from '../core/CalendarConfig';
|
2025-08-20 19:52:18 +02:00
|
|
|
import { CoreEvents } from '../constants/CoreEvents';
|
|
|
|
|
import { ResourceCalendarData, CalendarView } from '../types/CalendarTypes';
|
|
|
|
|
import { ViewStrategy, ViewContext } from '../strategies/ViewStrategy';
|
|
|
|
|
import { WeekViewStrategy } from '../strategies/WeekViewStrategy';
|
|
|
|
|
import { MonthViewStrategy } from '../strategies/MonthViewStrategy';
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Simplified GridManager focused on coordination, not implementation
|
2025-07-24 22:17:38 +02:00
|
|
|
*/
|
|
|
|
|
export class GridManager {
|
|
|
|
|
private container: HTMLElement | null = null;
|
2025-08-20 19:52:18 +02:00
|
|
|
private currentDate: Date = new Date();
|
|
|
|
|
private resourceData: ResourceCalendarData | null = null;
|
|
|
|
|
private currentStrategy: ViewStrategy;
|
|
|
|
|
private eventCleanup: (() => void)[] = [];
|
2025-07-24 22:17:38 +02:00
|
|
|
|
|
|
|
|
constructor() {
|
2025-08-20 19:52:18 +02:00
|
|
|
|
|
|
|
|
// Default to week view strategy
|
|
|
|
|
this.currentStrategy = new WeekViewStrategy();
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
this.init();
|
|
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
private init(): void {
|
|
|
|
|
this.findElements();
|
|
|
|
|
this.subscribeToEvents();
|
2025-07-25 23:31:25 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
private findElements(): void {
|
2025-08-20 19:52:18 +02:00
|
|
|
this.container = document.querySelector('swp-calendar-container');
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
private subscribeToEvents(): void {
|
2025-08-20 19:52:18 +02:00
|
|
|
// Listen for view changes to switch strategies
|
|
|
|
|
this.eventCleanup.push(
|
2025-08-20 20:22:51 +02:00
|
|
|
eventBus.on(CoreEvents.VIEW_CHANGED, (e: Event) => {
|
2025-08-20 19:52:18 +02:00
|
|
|
const detail = (e as CustomEvent).detail;
|
|
|
|
|
this.switchViewStrategy(detail.currentView);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Listen for config changes that affect rendering
|
|
|
|
|
this.eventCleanup.push(
|
2025-08-20 20:22:51 +02:00
|
|
|
eventBus.on(CoreEvents.REFRESH_REQUESTED, (e: Event) => {
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.eventCleanup.push(
|
2025-08-20 20:22:51 +02:00
|
|
|
eventBus.on(CoreEvents.WORKWEEK_CHANGED, () => {
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
|
|
|
|
})
|
|
|
|
|
);
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Switch to a different view strategy
|
|
|
|
|
*/
|
|
|
|
|
public switchViewStrategy(view: CalendarView): void {
|
|
|
|
|
|
|
|
|
|
// Clean up current strategy
|
|
|
|
|
this.currentStrategy.destroy();
|
|
|
|
|
|
|
|
|
|
// Create new strategy based on view
|
|
|
|
|
switch (view) {
|
|
|
|
|
case 'week':
|
|
|
|
|
case 'day':
|
|
|
|
|
this.currentStrategy = new WeekViewStrategy();
|
|
|
|
|
break;
|
|
|
|
|
case 'month':
|
|
|
|
|
this.currentStrategy = new MonthViewStrategy();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
this.currentStrategy = new WeekViewStrategy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Re-render with new strategy
|
|
|
|
|
this.render();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-10 23:06:03 +02:00
|
|
|
/**
|
|
|
|
|
* Set resource data for resource calendar mode
|
|
|
|
|
*/
|
|
|
|
|
public setResourceData(resourceData: ResourceCalendarData | null): void {
|
|
|
|
|
this.resourceData = resourceData;
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
2025-08-10 23:06:03 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Main render method - delegates to current strategy
|
2025-07-24 22:17:38 +02:00
|
|
|
*/
|
2025-08-20 19:52:18 +02:00
|
|
|
public async render(): Promise<void> {
|
|
|
|
|
if (!this.container) {
|
|
|
|
|
return;
|
2025-08-09 01:16:04 +02:00
|
|
|
}
|
2025-08-20 00:39:31 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
// Create context for strategy
|
|
|
|
|
const context: ViewContext = {
|
|
|
|
|
currentDate: this.currentDate,
|
|
|
|
|
container: this.container,
|
|
|
|
|
resourceData: this.resourceData
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Delegate to current strategy
|
|
|
|
|
this.currentStrategy.renderGrid(context);
|
|
|
|
|
|
|
|
|
|
// Get layout info from strategy
|
|
|
|
|
const layoutConfig = this.currentStrategy.getLayoutConfig();
|
2025-08-16 00:51:12 +02:00
|
|
|
|
2025-08-20 21:51:49 +02:00
|
|
|
// Get period range from current strategy
|
|
|
|
|
const periodRange = this.currentStrategy.getPeriodRange(this.currentDate);
|
2025-08-20 21:38:54 +02:00
|
|
|
|
2025-08-20 21:51:49 +02:00
|
|
|
|
|
|
|
|
// Emit grid rendered event with explicit date range
|
2025-08-20 19:52:18 +02:00
|
|
|
eventBus.emit(CoreEvents.GRID_RENDERED, {
|
|
|
|
|
container: this.container,
|
|
|
|
|
currentDate: this.currentDate,
|
2025-08-20 21:51:49 +02:00
|
|
|
startDate: periodRange.startDate,
|
|
|
|
|
endDate: periodRange.endDate,
|
2025-08-20 19:52:18 +02:00
|
|
|
layoutConfig: layoutConfig,
|
|
|
|
|
columnCount: layoutConfig.columnCount
|
2025-08-16 00:51:12 +02:00
|
|
|
});
|
2025-08-20 00:39:31 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
|
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Get current period label from strategy
|
2025-07-24 22:17:38 +02:00
|
|
|
*/
|
2025-08-20 19:52:18 +02:00
|
|
|
public getCurrentPeriodLabel(): string {
|
|
|
|
|
return this.currentStrategy.getPeriodLabel(this.currentDate);
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Navigate to next period using strategy
|
2025-07-24 22:17:38 +02:00
|
|
|
*/
|
2025-08-20 19:52:18 +02:00
|
|
|
public navigateNext(): void {
|
|
|
|
|
const nextDate = this.currentStrategy.getNextPeriod(this.currentDate);
|
|
|
|
|
this.currentDate = nextDate;
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
|
|
|
|
|
direction: 'next',
|
|
|
|
|
newDate: nextDate,
|
|
|
|
|
periodLabel: this.getCurrentPeriodLabel()
|
|
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Navigate to previous period using strategy
|
|
|
|
|
*/
|
|
|
|
|
public navigatePrevious(): void {
|
|
|
|
|
const prevDate = this.currentStrategy.getPreviousPeriod(this.currentDate);
|
|
|
|
|
this.currentDate = prevDate;
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
eventBus.emit(CoreEvents.PERIOD_CHANGED, {
|
|
|
|
|
direction: 'previous',
|
|
|
|
|
newDate: prevDate,
|
|
|
|
|
periodLabel: this.getCurrentPeriodLabel()
|
|
|
|
|
});
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-25 23:31:25 +02:00
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Navigate to today
|
2025-07-25 23:31:25 +02:00
|
|
|
*/
|
2025-08-20 19:52:18 +02:00
|
|
|
public navigateToToday(): void {
|
|
|
|
|
this.currentDate = new Date();
|
2025-07-25 23:31:25 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
eventBus.emit(CoreEvents.DATE_CHANGED, {
|
|
|
|
|
newDate: this.currentDate,
|
|
|
|
|
periodLabel: this.getCurrentPeriodLabel()
|
|
|
|
|
});
|
2025-07-25 23:31:25 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
this.render();
|
2025-07-25 23:31:25 +02:00
|
|
|
}
|
2025-08-20 19:52:18 +02:00
|
|
|
|
2025-07-24 22:17:38 +02:00
|
|
|
/**
|
2025-08-20 19:52:18 +02:00
|
|
|
* Get current view's display dates
|
2025-07-24 22:17:38 +02:00
|
|
|
*/
|
2025-08-20 19:52:18 +02:00
|
|
|
public getDisplayDates(): Date[] {
|
|
|
|
|
return this.currentStrategy.getDisplayDates(this.currentDate);
|
|
|
|
|
}
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
/**
|
|
|
|
|
* Clean up all resources
|
|
|
|
|
*/
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
|
|
|
|
|
// Clean up event listeners
|
|
|
|
|
this.eventCleanup.forEach(cleanup => cleanup());
|
|
|
|
|
this.eventCleanup = [];
|
|
|
|
|
|
|
|
|
|
// Clean up current strategy
|
|
|
|
|
this.currentStrategy.destroy();
|
2025-07-24 22:17:38 +02:00
|
|
|
|
2025-08-20 19:52:18 +02:00
|
|
|
// Clear references
|
|
|
|
|
this.container = null;
|
|
|
|
|
this.resourceData = null;
|
2025-07-24 22:17:38 +02:00
|
|
|
}
|
|
|
|
|
}
|