From 989c9bd69d05d1cdb7ae377b9ce66f6cde32d42d Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Mon, 3 Nov 2025 22:04:37 +0100 Subject: [PATCH] Batch update, WIP --- .../CalendarConfig.ts | 62 +------------------ .../ConfigManager.ts | 0 .../DateViewSettings.ts | 0 .../GridSettings.ts | 9 +++ .../ICalendarConfig.ts | 0 .../TimeFormatConfig.ts | 0 .../WorkWeekSettings.ts | 0 src/elements/SwpEventElement.ts | 6 +- src/index.ts | 4 +- src/managers/AllDayManager.ts | 2 +- src/managers/CalendarManager.ts | 4 +- src/managers/EventLayoutCoordinator.ts | 4 +- src/managers/EventManager.ts | 2 +- src/managers/EventStackManager.ts | 4 +- src/managers/HeaderManager.ts | 2 +- src/managers/ResizeHandleManager.ts | 4 +- src/managers/ViewManager.ts | 4 +- src/managers/WorkHoursManager.ts | 4 +- src/renderers/ColumnRenderer.ts | 6 +- src/renderers/DateHeaderRenderer.ts | 8 +-- src/renderers/EventRenderer.ts | 4 +- src/renderers/GridRenderer.ts | 4 +- src/utils/DateService.ts | 4 +- src/utils/PositionUtils.ts | 22 +++---- src/utils/TimeFormatter.ts | 32 +++++----- 25 files changed, 68 insertions(+), 123 deletions(-) rename src/{configuration => configurations}/CalendarConfig.ts (69%) rename src/{configuration => configurations}/ConfigManager.ts (100%) rename src/{configuration => configurations}/DateViewSettings.ts (100%) rename src/{configuration => configurations}/GridSettings.ts (63%) rename src/{configuration => configurations}/ICalendarConfig.ts (100%) rename src/{configuration => configurations}/TimeFormatConfig.ts (100%) rename src/{configuration => configurations}/WorkWeekSettings.ts (100%) diff --git a/src/configuration/CalendarConfig.ts b/src/configurations/CalendarConfig.ts similarity index 69% rename from src/configuration/CalendarConfig.ts rename to src/configurations/CalendarConfig.ts index a9c9517..c3fcb9f 100644 --- a/src/configuration/CalendarConfig.ts +++ b/src/configurations/CalendarConfig.ts @@ -97,68 +97,12 @@ export class Configuration { return Configuration._instance; } - // Computed properties - get minuteHeight(): number { - return this.gridSettings.hourHeight / 60; - } - - get totalHours(): number { - return this.gridSettings.dayEndHour - this.gridSettings.dayStartHour; - } - - get totalMinutes(): number { - return this.totalHours * 60; - } - - get slotsPerHour(): number { - return 60 / this.gridSettings.snapInterval; - } - - get totalSlots(): number { - return this.totalHours * this.slotsPerHour; - } - - get slotHeight(): number { - return this.gridSettings.hourHeight / this.slotsPerHour; - } - - // Backward compatibility getters - getGridSettings(): IGridSettings { - return this.gridSettings; - } - - getDateViewSettings(): IDateViewSettings { - return this.dateViewSettings; - } + // Helper methods getWorkWeekSettings(): IWorkWeekSettings { return WORK_WEEK_PRESETS[this.currentWorkWeek] || WORK_WEEK_PRESETS['standard']; } - getCurrentWorkWeek(): string { - return this.currentWorkWeek; - } - - getTimezone(): string { - return this.timeFormatConfig.timezone; - } - - getLocale(): string { - return this.timeFormatConfig.locale; - } - - getTimeFormatSettings(): ITimeFormatConfig { - return this.timeFormatConfig; - } - - is24HourFormat(): boolean { - return this.timeFormatConfig.use24HourFormat; - } - - getDateFormat(): 'locale' | 'technical' { - return this.timeFormatConfig.dateFormat; - } - setWorkWeek(workWeekId: string): void { if (WORK_WEEK_PRESETS[workWeekId]) { this.currentWorkWeek = workWeekId; @@ -169,10 +113,6 @@ export class Configuration { setSelectedDate(date: Date): void { this.selectedDate = date; } - - isValidSnapInterval(interval: number): boolean { - return [5, 10, 15, 30, 60].includes(interval); - } } // Backward compatibility alias diff --git a/src/configuration/ConfigManager.ts b/src/configurations/ConfigManager.ts similarity index 100% rename from src/configuration/ConfigManager.ts rename to src/configurations/ConfigManager.ts diff --git a/src/configuration/DateViewSettings.ts b/src/configurations/DateViewSettings.ts similarity index 100% rename from src/configuration/DateViewSettings.ts rename to src/configurations/DateViewSettings.ts diff --git a/src/configuration/GridSettings.ts b/src/configurations/GridSettings.ts similarity index 63% rename from src/configuration/GridSettings.ts rename to src/configurations/GridSettings.ts index 283de63..511e45a 100644 --- a/src/configuration/GridSettings.ts +++ b/src/configurations/GridSettings.ts @@ -14,3 +14,12 @@ export interface IGridSettings { showCurrentTime: boolean; showWorkHours: boolean; } + +/** + * Grid settings utility functions + */ +export namespace GridSettingsUtils { + export function isValidSnapInterval(interval: number): boolean { + return [5, 10, 15, 30, 60].includes(interval); + } +} diff --git a/src/configuration/ICalendarConfig.ts b/src/configurations/ICalendarConfig.ts similarity index 100% rename from src/configuration/ICalendarConfig.ts rename to src/configurations/ICalendarConfig.ts diff --git a/src/configuration/TimeFormatConfig.ts b/src/configurations/TimeFormatConfig.ts similarity index 100% rename from src/configuration/TimeFormatConfig.ts rename to src/configurations/TimeFormatConfig.ts diff --git a/src/configuration/WorkWeekSettings.ts b/src/configurations/WorkWeekSettings.ts similarity index 100% rename from src/configuration/WorkWeekSettings.ts rename to src/configurations/WorkWeekSettings.ts diff --git a/src/elements/SwpEventElement.ts b/src/elements/SwpEventElement.ts index cc5936c..6acbbb5 100644 --- a/src/elements/SwpEventElement.ts +++ b/src/elements/SwpEventElement.ts @@ -1,5 +1,5 @@ import { ICalendarEvent } from '../types/CalendarTypes'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { TimeFormatter } from '../utils/TimeFormatter'; import { PositionUtils } from '../utils/PositionUtils'; import { DateService } from '../utils/DateService'; @@ -137,7 +137,7 @@ export class SwpEventElement extends BaseSwpEventElement { this.style.height = `${newHeight}px`; // 2. Calculate new end time based on height - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const { hourHeight, snapInterval } = gridSettings; // Get current start time @@ -230,7 +230,7 @@ export class SwpEventElement extends BaseSwpEventElement { * Calculate start/end minutes from Y position */ private calculateTimesFromPosition(snappedY: number): { startMinutes: number; endMinutes: number } { - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const { hourHeight, dayStartHour, snapInterval } = gridSettings; // Get original duration diff --git a/src/index.ts b/src/index.ts index 2874e0e..908e0fc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,8 @@ // Main entry point for Calendar Plantempus import { Container } from '@novadi/core'; import { eventBus } from './core/EventBus'; -import { ConfigManager } from './configuration/ConfigManager'; -import { Configuration } from './configuration/CalendarConfig'; +import { ConfigManager } from './configurations/ConfigManager'; +import { Configuration } from './configurations/CalendarConfig'; import { URLManager } from './utils/URLManager'; import { IEventBus } from './types/CalendarTypes'; diff --git a/src/managers/AllDayManager.ts b/src/managers/AllDayManager.ts index fc82de7..9025b9f 100644 --- a/src/managers/AllDayManager.ts +++ b/src/managers/AllDayManager.ts @@ -1,7 +1,7 @@ // All-day row height management and animations import { eventBus } from '../core/EventBus'; -import { ALL_DAY_CONSTANTS } from '../configuration/CalendarConfig'; +import { ALL_DAY_CONSTANTS } from '../configurations/CalendarConfig'; import { AllDayEventRenderer } from '../renderers/AllDayEventRenderer'; import { AllDayLayoutEngine, IEventLayout } from '../utils/AllDayLayoutEngine'; import { IColumnBounds, ColumnDetectionUtils } from '../utils/ColumnDetectionUtils'; diff --git a/src/managers/CalendarManager.ts b/src/managers/CalendarManager.ts index 68fc38c..0ba320b 100644 --- a/src/managers/CalendarManager.ts +++ b/src/managers/CalendarManager.ts @@ -1,5 +1,5 @@ import { CoreEvents } from '../constants/CoreEvents'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { CalendarView, IEventBus } from '../types/CalendarTypes'; import { EventManager } from './EventManager'; import { GridManager } from './GridManager'; @@ -206,7 +206,7 @@ export class CalendarManager { this.eventBus.emit('workweek:header-update', { currentDate: this.currentDate, currentView: this.currentView, - workweek: this.config.getCurrentWorkWeek() + workweek: this.config.currentWorkWeek }); } diff --git a/src/managers/EventLayoutCoordinator.ts b/src/managers/EventLayoutCoordinator.ts index 6f18d6f..ad777c3 100644 --- a/src/managers/EventLayoutCoordinator.ts +++ b/src/managers/EventLayoutCoordinator.ts @@ -8,7 +8,7 @@ import { ICalendarEvent } from '../types/CalendarTypes'; import { EventStackManager, IEventGroup, IStackLink } from './EventStackManager'; import { PositionUtils } from '../utils/PositionUtils'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; export interface IGridGroupLayout { events: ICalendarEvent[]; @@ -59,7 +59,7 @@ export class EventLayoutCoordinator { // Find events that could be in GRID with first event // Use expanding search to find chains (A→B→C where each conflicts with next) - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const thresholdMinutes = gridSettings.gridStartThresholdMinutes; // Use refactored method for expanding grid candidates diff --git a/src/managers/EventManager.ts b/src/managers/EventManager.ts index 52ceefd..a52361e 100644 --- a/src/managers/EventManager.ts +++ b/src/managers/EventManager.ts @@ -1,6 +1,6 @@ import { IEventBus, ICalendarEvent } from '../types/CalendarTypes'; import { CoreEvents } from '../constants/CoreEvents'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { DateService } from '../utils/DateService'; import { IEventRepository } from '../repositories/IEventRepository'; diff --git a/src/managers/EventStackManager.ts b/src/managers/EventStackManager.ts index 7c701de..a3fca1d 100644 --- a/src/managers/EventStackManager.ts +++ b/src/managers/EventStackManager.ts @@ -14,7 +14,7 @@ */ import { ICalendarEvent } from '../types/CalendarTypes'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; export interface IStackLink { prev?: string; // Event ID of previous event in stack @@ -51,7 +51,7 @@ export class EventStackManager { if (events.length === 0) return []; // Get threshold from config - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const thresholdMinutes = gridSettings.gridStartThresholdMinutes; // Sort events by start time diff --git a/src/managers/HeaderManager.ts b/src/managers/HeaderManager.ts index c7c702d..bf6073a 100644 --- a/src/managers/HeaderManager.ts +++ b/src/managers/HeaderManager.ts @@ -1,5 +1,5 @@ import { eventBus } from '../core/EventBus'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { CoreEvents } from '../constants/CoreEvents'; import { IHeaderRenderer, IHeaderRenderContext } from '../renderers/DateHeaderRenderer'; import { IDragMouseEnterHeaderEventPayload, IDragMouseLeaveHeaderEventPayload, IHeaderReadyEventPayload } from '../types/EventTypes'; diff --git a/src/managers/ResizeHandleManager.ts b/src/managers/ResizeHandleManager.ts index 95c6b3a..863895a 100644 --- a/src/managers/ResizeHandleManager.ts +++ b/src/managers/ResizeHandleManager.ts @@ -1,6 +1,6 @@ import { eventBus } from '../core/EventBus'; import { CoreEvents } from '../constants/CoreEvents'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { IResizeEndEventPayload } from '../types/EventTypes'; type SwpEventEl = HTMLElement & { updateHeight?: (h: number) => void }; @@ -33,7 +33,7 @@ export class ResizeHandleManager { constructor(config: Configuration) { this.config = config; - const grid = this.config.getGridSettings(); + const grid = this.config.gridSettings; this.hourHeightPx = grid.hourHeight; this.snapMin = grid.snapInterval; this.minDurationMin = this.snapMin; // Use snap interval as minimum duration diff --git a/src/managers/ViewManager.ts b/src/managers/ViewManager.ts index 596564c..fed88ce 100644 --- a/src/managers/ViewManager.ts +++ b/src/managers/ViewManager.ts @@ -1,5 +1,5 @@ import { CalendarView, IEventBus } from '../types/CalendarTypes'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { CoreEvents } from '../constants/CoreEvents'; @@ -113,7 +113,7 @@ export class ViewManager { this.updateButtonGroup( this.getWorkweekButtons(), 'data-workweek', - this.config.getCurrentWorkWeek() + this.config.currentWorkWeek ); } diff --git a/src/managers/WorkHoursManager.ts b/src/managers/WorkHoursManager.ts index 1091b5b..886af11 100644 --- a/src/managers/WorkHoursManager.ts +++ b/src/managers/WorkHoursManager.ts @@ -1,7 +1,7 @@ // Work hours management for per-column scheduling import { DateService } from '../utils/DateService'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { PositionUtils } from '../utils/PositionUtils'; /** @@ -102,7 +102,7 @@ export class WorkHoursManager { return null; // Full day will be colored via CSS background } - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const dayStartHour = gridSettings.dayStartHour; const hourHeight = gridSettings.hourHeight; diff --git a/src/renderers/ColumnRenderer.ts b/src/renderers/ColumnRenderer.ts index 61226f8..62be950 100644 --- a/src/renderers/ColumnRenderer.ts +++ b/src/renderers/ColumnRenderer.ts @@ -1,6 +1,6 @@ // Column rendering strategy interface and implementations -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { DateService } from '../utils/DateService'; import { WorkHoursManager } from '../managers/WorkHoursManager'; @@ -36,10 +36,10 @@ export class DateColumnRenderer implements IColumnRenderer { render(columnContainer: HTMLElement, context: IColumnRenderContext): void { const { currentWeek, config } = context; - + const workWeekSettings = config.getWorkWeekSettings(); const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays); - const dateSettings = config.getDateViewSettings(); + const dateSettings = config.dateViewSettings; const daysToShow = dates.slice(0, dateSettings.weekDays); diff --git a/src/renderers/DateHeaderRenderer.ts b/src/renderers/DateHeaderRenderer.ts index 027354d..67d6e80 100644 --- a/src/renderers/DateHeaderRenderer.ts +++ b/src/renderers/DateHeaderRenderer.ts @@ -1,6 +1,6 @@ // Header rendering strategy interface and implementations -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { DateService } from '../utils/DateService'; /** @@ -33,13 +33,13 @@ export class DateHeaderRenderer implements IHeaderRenderer { calendarHeader.appendChild(allDayContainer); // Initialize date service with timezone and locale from config - const timezone = config.getTimezone(); - const locale = config.getLocale(); + const timezone = config.timeFormatConfig.timezone; + const locale = config.timeFormatConfig.locale; this.dateService = new DateService(config); const workWeekSettings = config.getWorkWeekSettings(); const dates = this.dateService.getWorkWeekDates(currentWeek, workWeekSettings.workDays); - const weekDays = config.getDateViewSettings().weekDays; + const weekDays = config.dateViewSettings.weekDays; const daysToShow = dates.slice(0, weekDays); daysToShow.forEach((date, index) => { diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 4e7b2a9..89ee2a0 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -1,7 +1,7 @@ // Event rendering strategy interface and implementations import { ICalendarEvent } from '../types/CalendarTypes'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { SwpEventElement } from '../elements/SwpEventElement'; import { PositionUtils } from '../utils/PositionUtils'; import { IColumnBounds } from '../utils/ColumnDetectionUtils'; @@ -312,7 +312,7 @@ export class DateEventRenderer implements IEventRenderer { // (e.g., if container starts at 07:00 and event starts at 08:15, offset = 75 min) const timeDiffMs = event.start.getTime() - containerStart.getTime(); const timeDiffMinutes = timeDiffMs / (1000 * 60); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const relativeTop = timeDiffMinutes > 0 ? (timeDiffMinutes / 60) * gridSettings.hourHeight : 0; // Events in grid columns are positioned absolutely within their column container diff --git a/src/renderers/GridRenderer.ts b/src/renderers/GridRenderer.ts index d070f97..72eb8ae 100644 --- a/src/renderers/GridRenderer.ts +++ b/src/renderers/GridRenderer.ts @@ -1,4 +1,4 @@ -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { CalendarView } from '../types/CalendarTypes'; import { IColumnRenderer, IColumnRenderContext } from './ColumnRenderer'; import { eventBus } from '../core/EventBus'; @@ -179,7 +179,7 @@ export class GridRenderer { private createOptimizedTimeAxis(): HTMLElement { const timeAxis = document.createElement('swp-time-axis'); const timeAxisContent = document.createElement('swp-time-axis-content'); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const startHour = gridSettings.dayStartHour; const endHour = gridSettings.dayEndHour; diff --git a/src/utils/DateService.ts b/src/utils/DateService.ts index 14723c7..44e230e 100644 --- a/src/utils/DateService.ts +++ b/src/utils/DateService.ts @@ -29,13 +29,13 @@ import { fromZonedTime, formatInTimeZone } from 'date-fns-tz'; -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; export class DateService { private timezone: string; constructor(config: Configuration) { - this.timezone = config.getTimezone(); + this.timezone = config.timeFormatConfig.timezone; } // ============================================ diff --git a/src/utils/PositionUtils.ts b/src/utils/PositionUtils.ts index 526db61..3ec70dc 100644 --- a/src/utils/PositionUtils.ts +++ b/src/utils/PositionUtils.ts @@ -1,4 +1,4 @@ -import { Configuration } from '../configuration/CalendarConfig'; +import { Configuration } from '../configurations/CalendarConfig'; import { IColumnBounds } from './ColumnDetectionUtils'; import { DateService } from './DateService'; import { TimeFormatter } from './TimeFormatter'; @@ -22,7 +22,7 @@ export class PositionUtils { * Convert minutes to pixels */ public minutesToPixels(minutes: number): number { - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const pixelsPerHour = gridSettings.hourHeight; return (minutes / 60) * pixelsPerHour; } @@ -31,7 +31,7 @@ export class PositionUtils { * Convert pixels to minutes */ public pixelsToMinutes(pixels: number): number { - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const pixelsPerHour = gridSettings.hourHeight; return (pixels / pixelsPerHour) * 60; } @@ -41,7 +41,7 @@ export class PositionUtils { */ public timeToPixels(timeString: string): number { const totalMinutes = this.dateService.timeToMinutes(timeString); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const dayStartMinutes = gridSettings.dayStartHour * 60; const minutesFromDayStart = totalMinutes - dayStartMinutes; @@ -53,7 +53,7 @@ export class PositionUtils { */ public dateToPixels(date: Date): number { const totalMinutes = this.dateService.getMinutesSinceMidnight(date); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const dayStartMinutes = gridSettings.dayStartHour * 60; const minutesFromDayStart = totalMinutes - dayStartMinutes; @@ -65,7 +65,7 @@ export class PositionUtils { */ public pixelsToTime(pixels: number): string { const minutes = this.pixelsToMinutes(pixels); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const dayStartMinutes = gridSettings.dayStartHour * 60; const totalMinutes = dayStartMinutes + minutes; @@ -109,7 +109,7 @@ export class PositionUtils { * Snap position til grid interval */ public snapToGrid(pixels: number): number { - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const snapInterval = gridSettings.snapInterval; const snapPixels = this.minutesToPixels(snapInterval); @@ -121,7 +121,7 @@ export class PositionUtils { */ public snapTimeToInterval(timeString: string): string { const totalMinutes = this.dateService.timeToMinutes(timeString); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const snapInterval = gridSettings.snapInterval; const snappedMinutes = Math.round(totalMinutes / snapInterval) * snapInterval; @@ -182,7 +182,7 @@ export class PositionUtils { */ public isWithinWorkHours(timeString: string): boolean { const [hours] = timeString.split(':').map(Number); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; return hours >= gridSettings.workStartHour && hours < gridSettings.workEndHour; } @@ -191,7 +191,7 @@ export class PositionUtils { */ public isWithinDayBounds(timeString: string): boolean { const [hours] = timeString.split(':').map(Number); - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; return hours >= gridSettings.dayStartHour && hours < gridSettings.dayEndHour; } @@ -207,7 +207,7 @@ export class PositionUtils { * Hent maksimum event højde i pixels (hele dagen) */ public getMaximumEventHeight(): number { - const gridSettings = this.config.getGridSettings(); + const gridSettings = this.config.gridSettings; const dayDurationHours = gridSettings.dayEndHour - gridSettings.dayStartHour; return dayDurationHours * gridSettings.hourHeight; } diff --git a/src/utils/TimeFormatter.ts b/src/utils/TimeFormatter.ts index d9d53a2..fa73366 100644 --- a/src/utils/TimeFormatter.ts +++ b/src/utils/TimeFormatter.ts @@ -9,32 +9,24 @@ */ import { DateService } from './DateService'; - -export interface ITimeFormatSettings { - timezone: string; - use24HourFormat: boolean; - locale: string; - dateFormat: 'locale' | 'technical'; - showSeconds: boolean; -} +import { ITimeFormatConfig } from '../configurations/TimeFormatConfig'; export class TimeFormatter { - private static settings: ITimeFormatSettings = { - timezone: 'Europe/Copenhagen', // Default to Denmark - use24HourFormat: true, // 24-hour format standard in Denmark - locale: 'da-DK', // Danish locale - dateFormat: 'technical', // Use technical format yyyy-mm-dd hh:mm:ss - showSeconds: false // Don't show seconds by default - }; + private static settings: ITimeFormatConfig | null = null; // DateService will be initialized lazily to avoid circular dependency with CalendarConfig private static dateService: DateService | null = null; private static getDateService(): DateService { if (!TimeFormatter.dateService) { + if (!TimeFormatter.settings) { + throw new Error('TimeFormatter must be configured before use. Call TimeFormatter.configure() first.'); + } // Create a minimal config object for DateService const config = { - getTimezone: () => TimeFormatter.settings.timezone + timeFormatConfig: { + timezone: TimeFormatter.settings.timezone + } }; TimeFormatter.dateService = new DateService(config as any); } @@ -43,9 +35,10 @@ export class TimeFormatter { /** * Configure time formatting settings + * Must be called before using TimeFormatter */ - static configure(settings: Partial): void { - TimeFormatter.settings = { ...TimeFormatter.settings, ...settings }; + static configure(settings: ITimeFormatConfig): void { + TimeFormatter.settings = settings; // Reset DateService to pick up new timezone TimeFormatter.dateService = null; } @@ -71,6 +64,9 @@ export class TimeFormatter { * @returns Formatted time string (e.g., "09:00") */ private static format24Hour(date: Date): string { + if (!TimeFormatter.settings) { + throw new Error('TimeFormatter must be configured before use. Call TimeFormatter.configure() first.'); + } const localDate = TimeFormatter.convertToLocalTime(date); return TimeFormatter.getDateService().formatTime(localDate, TimeFormatter.settings.showSeconds); }