// Calendar configuration management import { eventBus } from './EventBus'; import { EventTypes } from '../constants/EventTypes'; import { CalendarConfig as ICalendarConfig, ViewType, CalendarType } from '../types/CalendarTypes'; /** * View-specific settings interface */ interface ViewSettings { columns: number; showAllDay: boolean; scrollToHour: number | null; } /** * Calendar configuration management */ export class CalendarConfig { private config: ICalendarConfig; private calendarType: CalendarType = 'date'; private selectedDate: Date | null = null; constructor() { this.config = { // View settings view: 'week', // 'day' | 'week' | 'month' weekDays: 7, // 4-7 days for week view firstDayOfWeek: 1, // 0 = Sunday, 1 = Monday // Time settings dayStartHour: 0, // Calendar starts at midnight (default) dayEndHour: 24, // Calendar ends at midnight (default) workStartHour: 8, // Work hours start workEndHour: 17, // Work hours end snapInterval: 15, // Minutes: 5, 10, 15, 30, 60 // Display settings hourHeight: 60, // Pixels per hour showCurrentTime: true, showWorkHours: true, fitToWidth: false, // Fit columns to calendar width (no horizontal scroll) // Scrollbar styling scrollbarWidth: 16, // Width of scrollbar in pixels scrollbarColor: '#666', // Scrollbar thumb color scrollbarTrackColor: '#f0f0f0', // Scrollbar track color scrollbarHoverColor: '#b53f7aff', // Scrollbar thumb hover color scrollbarBorderRadius: 6, // Border radius for scrollbar thumb // Interaction settings allowDrag: true, allowResize: true, allowCreate: true, // API settings apiEndpoint: '/api/events', dateFormat: 'YYYY-MM-DD', timeFormat: 'HH:mm', // Feature flags enableSearch: true, enableTouch: true, // Event defaults defaultEventDuration: 60, // Minutes minEventDuration: 15, // Will be same as snapInterval maxEventDuration: 480 // 8 hours }; // Set computed values this.config.minEventDuration = this.config.snapInterval; // Load calendar type from URL parameter this.loadCalendarType(); // Load from data attributes this.loadFromDOM(); } /** * Load calendar type and date from URL parameters */ private loadCalendarType(): void { const urlParams = new URLSearchParams(window.location.search); const typeParam = urlParams.get('type'); const dateParam = urlParams.get('date'); // Set calendar type if (typeParam === 'resource' || typeParam === 'date') { this.calendarType = typeParam; console.log(`CalendarConfig: Calendar type set to '${this.calendarType}' from URL parameter`); } else { this.calendarType = 'date'; // Default console.log(`CalendarConfig: Calendar type defaulted to '${this.calendarType}'`); } // Set selected date if (dateParam) { const parsedDate = new Date(dateParam); if (!isNaN(parsedDate.getTime())) { this.selectedDate = parsedDate; console.log(`CalendarConfig: Selected date set to '${this.selectedDate.toISOString()}' from URL parameter`); } else { console.warn(`CalendarConfig: Invalid date parameter '${dateParam}', using current date`); this.selectedDate = new Date(); } } else { this.selectedDate = new Date(); // Default to today console.log(`CalendarConfig: Selected date defaulted to today: ${this.selectedDate.toISOString()}`); } } /** * Load configuration from DOM data attributes */ private loadFromDOM(): void { const calendar = document.querySelector('swp-calendar') as HTMLElement; if (!calendar) return; // Read data attributes const attrs = calendar.dataset; if (attrs.view) this.config.view = attrs.view as ViewType; if (attrs.weekDays) this.config.weekDays = parseInt(attrs.weekDays); if (attrs.snapInterval) this.config.snapInterval = parseInt(attrs.snapInterval); if (attrs.dayStartHour) this.config.dayStartHour = parseInt(attrs.dayStartHour); if (attrs.dayEndHour) this.config.dayEndHour = parseInt(attrs.dayEndHour); if (attrs.hourHeight) this.config.hourHeight = parseInt(attrs.hourHeight); if (attrs.fitToWidth !== undefined) this.config.fitToWidth = attrs.fitToWidth === 'true'; } /** * Get a config value */ get(key: K): ICalendarConfig[K] { return this.config[key]; } /** * Set a config value */ set(key: K, value: ICalendarConfig[K]): void { const oldValue = this.config[key]; this.config[key] = value; // Update computed values if (key === 'snapInterval') { this.config.minEventDuration = value as number; } // Emit config update event eventBus.emit(EventTypes.CONFIG_UPDATE, { key, value, oldValue }); } /** * Update multiple config values */ update(updates: Partial): void { Object.entries(updates).forEach(([key, value]) => { this.set(key as keyof ICalendarConfig, value); }); } /** * Get all config */ getAll(): ICalendarConfig { return { ...this.config }; } /** * Calculate derived values */ get minuteHeight(): number { return this.config.hourHeight / 60; } get totalHours(): number { return this.config.dayEndHour - this.config.dayStartHour; } get totalMinutes(): number { return this.totalHours * 60; } get slotsPerHour(): number { return 60 / this.config.snapInterval; } get totalSlots(): number { return this.totalHours * this.slotsPerHour; } get slotHeight(): number { return this.config.hourHeight / this.slotsPerHour; } /** * Validate snap interval */ isValidSnapInterval(interval: number): boolean { return [5, 10, 15, 30, 60].includes(interval); } /** * Get view-specific settings */ getViewSettings(view: ViewType = this.config.view): ViewSettings { const settings: Record = { day: { columns: 1, showAllDay: true, scrollToHour: 8 }, week: { columns: this.config.weekDays, showAllDay: true, scrollToHour: 8 }, month: { columns: 7, showAllDay: false, scrollToHour: null } }; return settings[view] || settings.week; } /** * Get calendar type */ getCalendarType(): CalendarType { return this.calendarType; } /** * Set calendar type */ setCalendarType(type: CalendarType): void { const oldType = this.calendarType; this.calendarType = type; // Emit calendar type change event eventBus.emit(EventTypes.CALENDAR_TYPE_CHANGED, { oldType, newType: type }); } /** * Get selected date */ getSelectedDate(): Date | null { return this.selectedDate; } /** * Set selected date */ setSelectedDate(date: Date): void { this.selectedDate = date; // Emit date change event eventBus.emit(EventTypes.SELECTED_DATE_CHANGED, { date: date }); } } // Create singleton instance export const calendarConfig = new CalendarConfig();