// js/core/CalendarConfig.js import { eventBus } from './EventBus.js'; import { EventTypes } from '../types/EventTypes.js'; /** * Calendar configuration management */ export class CalendarConfig { 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: 7, // Calendar starts at 7 AM dayEndHour: 19, // Calendar ends at 7 PM 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, // 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: null, // Will be same as snapInterval maxEventDuration: 480 // 8 hours }; // Set computed values this.config.minEventDuration = this.config.snapInterval; // Load from data attributes this.loadFromDOM(); } /** * Load configuration from DOM data attributes */ loadFromDOM() { const calendar = document.querySelector('swp-calendar'); if (!calendar) return; // Read data attributes const attrs = calendar.dataset; if (attrs.view) this.config.view = attrs.view; 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); } /** * Get a config value * @param {string} key * @returns {*} */ get(key) { return this.config[key]; } /** * Set a config value * @param {string} key * @param {*} value */ set(key, value) { const oldValue = this.config[key]; this.config[key] = value; // Update computed values if (key === 'snapInterval') { this.config.minEventDuration = value; } // Emit config update event eventBus.emit(EventTypes.CONFIG_UPDATE, { key, value, oldValue }); } /** * Update multiple config values * @param {Object} updates */ update(updates) { Object.entries(updates).forEach(([key, value]) => { this.set(key, value); }); } /** * Get all config * @returns {Object} */ getAll() { return { ...this.config }; } /** * Calculate derived values */ get minuteHeight() { return this.config.hourHeight / 60; } get totalHours() { return this.config.dayEndHour - this.config.dayStartHour; } get totalMinutes() { return this.totalHours * 60; } get slotsPerHour() { return 60 / this.config.snapInterval; } get totalSlots() { return this.totalHours * this.slotsPerHour; } get slotHeight() { return this.config.hourHeight / this.slotsPerHour; } /** * Validate snap interval * @param {number} interval * @returns {boolean} */ isValidSnapInterval(interval) { return [5, 10, 15, 30, 60].includes(interval); } /** * Get view-specific settings * @param {string} view * @returns {Object} */ getViewSettings(view = this.config.view) { const settings = { 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; } } // Create singleton instance export const calendarConfig = new CalendarConfig();