diff --git a/src/core/EventBus.ts b/src/core/EventBus.ts index 444b7cc..41b49a0 100644 --- a/src/core/EventBus.ts +++ b/src/core/EventBus.ts @@ -59,14 +59,14 @@ export class EventBus implements IEventBus { /** * Emit an event via DOM CustomEvent */ - emit(eventType: string, detail: any = {}): boolean { + emit(eventType: string, detail: unknown = {}): boolean { // Validate eventType - if (!eventType || typeof eventType !== 'string') { + if (!eventType) { return false; } const event = new CustomEvent(eventType, { - detail, + detail: detail ?? {}, bubbles: true, cancelable: true }); @@ -78,7 +78,7 @@ export class EventBus implements IEventBus { this.eventLog.push({ type: eventType, - detail, + detail: detail ?? {}, timestamp: Date.now() }); @@ -89,7 +89,7 @@ export class EventBus implements IEventBus { /** * Log event with console grouping */ - private logEventWithGrouping(eventType: string, detail: any): void { + private logEventWithGrouping(eventType: string, detail: unknown): void { // Extract category from event type (e.g., 'calendar:datechanged' → 'calendar') const category = this.extractCategory(eventType); @@ -108,7 +108,7 @@ export class EventBus implements IEventBus { * Extract category from event type */ private extractCategory(eventType: string): string { - if (!eventType || typeof eventType !== 'string') { + if (!eventType) { return 'unknown'; } diff --git a/src/factories/ManagerFactory.ts b/src/factories/ManagerFactory.ts index acdf6b1..d35d38c 100644 --- a/src/factories/ManagerFactory.ts +++ b/src/factories/ManagerFactory.ts @@ -8,6 +8,7 @@ import { ViewManager } from '../managers/ViewManager'; import { CalendarManager } from '../managers/CalendarManager'; import { DragDropManager } from '../managers/DragDropManager'; import { AllDayManager } from '../managers/AllDayManager'; +import { CalendarManagers } from '../types/ManagerTypes'; /** * Factory for creating and managing calendar managers with proper dependency injection @@ -27,17 +28,7 @@ export class ManagerFactory { /** * Create all managers with proper dependency injection */ - public createManagers(eventBus: IEventBus): { - eventManager: EventManager; - eventRenderer: EventRenderingService; - gridManager: GridManager; - scrollManager: ScrollManager; - navigationManager: NavigationManager; - viewManager: ViewManager; - calendarManager: CalendarManager; - dragDropManager: DragDropManager; - allDayManager: AllDayManager; - } { + public createManagers(eventBus: IEventBus): CalendarManagers { // Create managers in dependency order const eventManager = new EventManager(eventBus); @@ -75,13 +66,10 @@ export class ManagerFactory { /** * Initialize all managers in the correct order */ - public async initializeManagers(managers: { - calendarManager: CalendarManager; - [key: string]: any; - }): Promise { + public async initializeManagers(managers: CalendarManagers): Promise { try { - await managers.calendarManager.initialize(); + await managers.calendarManager.initialize?.(); } catch (error) { throw error; } diff --git a/src/index.ts b/src/index.ts index a412dd0..f9c0049 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,16 @@ // Main entry point for Calendar Plantempus -import { eventBus } from './core/EventBus.js'; -import { calendarConfig } from './core/CalendarConfig.js'; -import { CalendarTypeFactory } from './factories/CalendarTypeFactory.js'; -import { ManagerFactory } from './factories/ManagerFactory.js'; -import { DateCalculator } from './utils/DateCalculator.js'; -import { URLManager } from './utils/URLManager.js'; +import { eventBus } from './core/EventBus'; +import { calendarConfig } from './core/CalendarConfig'; +import { CalendarTypeFactory } from './factories/CalendarTypeFactory'; +import { ManagerFactory } from './factories/ManagerFactory'; +import { DateCalculator } from './utils/DateCalculator'; +import { URLManager } from './utils/URLManager'; +import { CalendarManagers } from './types/ManagerTypes'; /** * Handle deep linking functionality after managers are initialized */ -async function handleDeepLinking(managers: any): Promise { +async function handleDeepLinking(managers: CalendarManagers): Promise { try { const urlManager = new URLManager(eventBus); const eventId = urlManager.parseEventIdFromURL(); @@ -58,8 +59,12 @@ async function initializeCalendar(): Promise { // Handle deep linking after managers are initialized await handleDeepLinking(managers); - // Expose to window for debugging - (window as any).calendarDebug = { + // Expose to window for debugging (with proper typing) + (window as Window & { + calendarDebug?: { + eventBus: typeof eventBus; + } & CalendarManagers; + }).calendarDebug = { eventBus, ...managers }; diff --git a/src/interfaces/IManager.ts b/src/interfaces/IManager.ts index e8ee254..37dd4f0 100644 --- a/src/interfaces/IManager.ts +++ b/src/interfaces/IManager.ts @@ -1,3 +1,5 @@ +import { CalendarEvent } from '../types/CalendarTypes'; + /** * Base interface for all managers */ @@ -23,8 +25,8 @@ export interface IManager { */ export interface IEventManager extends IManager { loadData(): Promise; - getEvents(): any[]; - getEventsForPeriod(startDate: Date, endDate: Date): any[]; + getEvents(): CalendarEvent[]; + getEventsForPeriod(startDate: Date, endDate: Date): CalendarEvent[]; } /** diff --git a/src/managers/AllDayManager.ts b/src/managers/AllDayManager.ts index bb61afe..0d5d533 100644 --- a/src/managers/AllDayManager.ts +++ b/src/managers/AllDayManager.ts @@ -10,6 +10,7 @@ import { DragMoveEventPayload, DragEndEventPayload } from '../types/EventTypes'; +import { DragOffset, MousePosition } from '../types/DragDropTypes'; /** * AllDayManager - Handles all-day row height animations and management @@ -102,7 +103,7 @@ export class AllDayManager { console.log('🎯 AllDayManager: Ending drag for all-day event', { eventId }); - this.handleDragEnd(draggedElement, dragClone as HTMLElement, finalPosition.column); + this.handleDragEnd(draggedElement, dragClone as HTMLElement, { column: finalPosition.column || '', y: 0 }); }); // Listen for drag cancellation to recalculate height @@ -374,7 +375,7 @@ export class AllDayManager { /** * Handle drag start for all-day events */ - private handleDragStart(originalElement: HTMLElement, eventId: string, mouseOffset: any): void { + private handleDragStart(originalElement: HTMLElement, eventId: string, mouseOffset: DragOffset): void { // Create clone const clone = originalElement.cloneNode(true) as HTMLElement; clone.dataset.eventId = `clone-${eventId}`; @@ -409,7 +410,7 @@ export class AllDayManager { /** * Handle drag move for all-day events */ - private handleDragMove(dragClone: HTMLElement, mousePosition: any): void { + private handleDragMove(dragClone: HTMLElement, mousePosition: MousePosition): void { // Calculate grid column based on mouse position const dayHeaders = document.querySelectorAll('swp-day-header'); let targetColumn = 1; @@ -434,7 +435,7 @@ export class AllDayManager { /** * Handle drag end for all-day events */ - private handleDragEnd(originalElement: HTMLElement, dragClone: HTMLElement, finalPosition: any): void { + private handleDragEnd(originalElement: HTMLElement, dragClone: HTMLElement, finalPosition: { column: string; y: number }): void { // Normalize clone const cloneId = dragClone.dataset.eventId; diff --git a/src/managers/CalendarManager.ts b/src/managers/CalendarManager.ts index 1cae7ed..e09b0df 100644 --- a/src/managers/CalendarManager.ts +++ b/src/managers/CalendarManager.ts @@ -1,14 +1,15 @@ -import { EventBus } from '../core/EventBus.js'; -import { CoreEvents } from '../constants/CoreEvents.js'; -import { calendarConfig } from '../core/CalendarConfig.js'; -import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes.js'; -import { EventManager } from './EventManager.js'; -import { GridManager } from './GridManager.js'; -import { HeaderManager } from './HeaderManager.js'; -import { EventRenderingService } from '../renderers/EventRendererManager.js'; -import { ScrollManager } from './ScrollManager.js'; -import { DateCalculator } from '../utils/DateCalculator.js'; -import { EventFilterManager } from './EventFilterManager.js'; +import { EventBus } from '../core/EventBus'; +import { CoreEvents } from '../constants/CoreEvents'; +import { calendarConfig } from '../core/CalendarConfig'; +import { CalendarEvent, CalendarView, IEventBus } from '../types/CalendarTypes'; +import { EventManager } from './EventManager'; +import { GridManager } from './GridManager'; +import { HeaderManager } from './HeaderManager'; +import { EventRenderingService } from '../renderers/EventRendererManager'; +import { ScrollManager } from './ScrollManager'; +import { DateCalculator } from '../utils/DateCalculator'; +import { EventFilterManager } from './EventFilterManager'; +import { InitializationReport } from '../types/ManagerTypes'; /** * CalendarManager - Main coordinator for all calendar managers @@ -65,7 +66,7 @@ export class CalendarManager { // Step 2: Pass data to GridManager and render grid structure if (calendarType === 'resource') { const resourceData = this.eventManager.getResourceData(); - this.gridManager.setResourceData(resourceData); + this.gridManager.setResourceData(this.eventManager.getRawData() as import('../types/CalendarTypes').ResourceCalendarData); } await this.gridManager.render(); @@ -211,12 +212,17 @@ export class CalendarManager { /** * Get initialization report for debugging */ - public getInitializationReport(): any { + public getInitializationReport(): InitializationReport { return { - isInitialized: this.isInitialized, - currentView: this.currentView, - currentDate: this.currentDate, - initializationTime: 'N/A - simple initialization' + initialized: this.isInitialized, + timestamp: Date.now(), + managers: { + calendar: { initialized: this.isInitialized }, + event: { initialized: true }, + grid: { initialized: true }, + header: { initialized: true }, + scroll: { initialized: true } + } }; } diff --git a/src/managers/EventFilterManager.ts b/src/managers/EventFilterManager.ts index e4c306d..5845186 100644 --- a/src/managers/EventFilterManager.ts +++ b/src/managers/EventFilterManager.ts @@ -10,13 +10,19 @@ import { CalendarEvent } from '../types/CalendarTypes'; // Import Fuse.js from npm import Fuse from 'fuse.js'; +interface FuseResult { + item: CalendarEvent; + refIndex: number; + score?: number; +} + export class EventFilterManager { private searchInput: HTMLInputElement | null = null; private allEvents: CalendarEvent[] = []; private matchingEventIds: Set = new Set(); private isFilterActive: boolean = false; private frameRequest: number | null = null; - private fuse: any = null; + private fuse: Fuse | null = null; constructor() { // Wait for DOM to be ready before initializing @@ -119,7 +125,7 @@ export class EventFilterManager { // Extract matching event IDs this.matchingEventIds.clear(); - results.forEach((result: any) => { + results.forEach((result: FuseResult) => { if (result.item && result.item.id) { this.matchingEventIds.add(result.item.id); } diff --git a/src/managers/EventManager.ts b/src/managers/EventManager.ts index 8a7925a..4a9252c 100644 --- a/src/managers/EventManager.ts +++ b/src/managers/EventManager.ts @@ -3,6 +3,17 @@ import { IEventBus, CalendarEvent, ResourceCalendarData } from '../types/Calenda import { CoreEvents } from '../constants/CoreEvents'; import { calendarConfig } from '../core/CalendarConfig'; import { DateCalculator } from '../utils/DateCalculator'; +import { ResourceData } from '../types/ManagerTypes'; + +interface RawEventData { + id: string; + title: string; + start: string | Date; + end: string | Date; + color?: string; + allDay?: boolean; + [key: string]: unknown; +} /** * EventManager - Optimized event lifecycle and CRUD operations @@ -11,7 +22,7 @@ import { DateCalculator } from '../utils/DateCalculator'; export class EventManager { private eventBus: IEventBus; private events: CalendarEvent[] = []; - private rawData: any = null; + private rawData: ResourceCalendarData | RawEventData[] | null = null; private eventCache = new Map(); // Cache for period queries private lastCacheKey: string = ''; @@ -57,7 +68,7 @@ export class EventManager { /** * Optimized data processing with better type safety */ - private processCalendarData(calendarType: string, data: any): CalendarEvent[] { + private processCalendarData(calendarType: string, data: ResourceCalendarData | RawEventData[]): CalendarEvent[] { if (calendarType === 'resource') { const resourceData = data as ResourceCalendarData; return resourceData.resources.flatMap(resource => @@ -72,10 +83,14 @@ export class EventManager { ); } - return data.map((event: any) => ({ + const eventData = data as RawEventData[]; + return eventData.map((event): CalendarEvent => ({ ...event, start: new Date(event.start), - end: new Date(event.end) + end: new Date(event.end), + type: 'event', + allDay: event.allDay || false, + syncStatus: 'synced' as const })); } @@ -97,7 +112,24 @@ export class EventManager { /** * Get raw resource data for resource calendar mode */ - public getResourceData(): any { + public getResourceData(): ResourceData | null { + if (!this.rawData || !('resources' in this.rawData)) { + return null; + } + return { + resources: this.rawData.resources.map(r => ({ + id: r.employeeId || r.name, // Use employeeId as id, fallback to name + name: r.name, + type: r.employeeId ? 'employee' : 'resource', + color: 'blue' // Default color since Resource interface doesn't have color + })) + }; + } + + /** + * Get raw data for compatibility + */ + public getRawData(): ResourceCalendarData | RawEventData[] | null { return this.rawData; } diff --git a/src/managers/GridManager.ts b/src/managers/GridManager.ts index f75bf75..c0bac0b 100644 --- a/src/managers/GridManager.ts +++ b/src/managers/GridManager.ts @@ -264,7 +264,7 @@ export class GridManager { /** * Get layout config for current view */ - private getLayoutConfig(): any { + private getLayoutConfig(): { columnCount: number; type: string } { switch (this.currentView) { case 'week': return { diff --git a/src/managers/NavigationManager.ts b/src/managers/NavigationManager.ts index f03c9b4..892afb9 100644 --- a/src/managers/NavigationManager.ts +++ b/src/managers/NavigationManager.ts @@ -1,9 +1,9 @@ -import { IEventBus } from '../types/CalendarTypes.js'; -import { EventRenderingService } from '../renderers/EventRendererManager.js'; -import { DateCalculator } from '../utils/DateCalculator.js'; -import { CoreEvents } from '../constants/CoreEvents.js'; -import { NavigationRenderer } from '../renderers/NavigationRenderer.js'; -import { calendarConfig } from '../core/CalendarConfig.js'; +import { IEventBus } from '../types/CalendarTypes'; +import { EventRenderingService } from '../renderers/EventRendererManager'; +import { DateCalculator } from '../utils/DateCalculator'; +import { CoreEvents } from '../constants/CoreEvents'; +import { NavigationRenderer } from '../renderers/NavigationRenderer'; +import { calendarConfig } from '../core/CalendarConfig'; /** * NavigationManager handles calendar navigation (prev/next/today buttons) diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 2f56bc0..5d69d94 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -8,6 +8,7 @@ import { OverlapDetector, OverlapResult } from '../utils/OverlapDetector'; import { SwpEventElement } from '../elements/SwpEventElement'; import { TimeFormatter } from '../utils/TimeFormatter'; import { PositionUtils } from '../utils/PositionUtils'; +import { DragOffset, StackLinkData } from '../types/DragDropTypes'; /** * Interface for event rendering strategies @@ -15,8 +16,8 @@ import { PositionUtils } from '../utils/PositionUtils'; export interface EventRendererStrategy { renderEvents(events: CalendarEvent[], container: HTMLElement): void; clearEvents(container?: HTMLElement): void; - handleDragStart?(originalElement: HTMLElement, eventId: string, mouseOffset: any, column: string): void; - handleDragMove?(eventId: string, snappedY: number, column: string, mouseOffset: any): void; + handleDragStart?(originalElement: HTMLElement, eventId: string, mouseOffset: DragOffset, column: string): void; + handleDragMove?(eventId: string, snappedY: number, column: string, mouseOffset: DragOffset): void; handleDragAutoScroll?(eventId: string, snappedY: number): void; handleDragEnd?(eventId: string, originalElement: HTMLElement, draggedClone: HTMLElement, finalColumn: string, finalY: number): void; handleEventClick?(eventId: string, originalElement: HTMLElement): void; @@ -159,7 +160,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { /** * Handle drag start event */ - public handleDragStart(originalElement: HTMLElement, eventId: string, mouseOffset: any, column: string): void { + public handleDragStart(originalElement: HTMLElement, eventId: string, mouseOffset: DragOffset, column: string): void { this.originalEvent = originalElement; // Remove stacking styling during drag will be handled by new system @@ -195,7 +196,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { /** * Handle drag move event */ - public handleDragMove(eventId: string, snappedY: number, column: string, mouseOffset: any): void { + public handleDragMove(eventId: string, snappedY: number, column: string, mouseOffset: DragOffset): void { if (!this.draggedClone) return; // Update position @@ -259,7 +260,7 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { const allStackEventIds: Set = new Set(); // Recursive funktion til at traversere stack chain - const traverseStack = (linkData: any, visitedIds: Set) => { + const traverseStack = (linkData: StackLinkData, visitedIds: Set) => { if (linkData.prev && !visitedIds.has(linkData.prev)) { visitedIds.add(linkData.prev); const prevElement = document.querySelector(`swp-time-grid [data-event-id="${linkData.prev}"]`) as HTMLElement; diff --git a/src/renderers/EventRendererManager.ts b/src/renderers/EventRendererManager.ts index 2f3fcf2..73c9166 100644 --- a/src/renderers/EventRendererManager.ts +++ b/src/renderers/EventRendererManager.ts @@ -275,7 +275,7 @@ export class EventRenderingService { /** * Handle conversion from all-day event to time event */ - private handleConvertToTimeEvent(draggedElement: HTMLElement, mousePosition: any, column: string): void { + private handleConvertToTimeEvent(draggedElement: HTMLElement, mousePosition: { x: number; y: number }, column: string): void { // Use the provided draggedElement directly const allDayClone = draggedElement; const draggedEventId = draggedElement?.dataset.eventId?.replace('clone-', '') || ''; diff --git a/src/renderers/GridStyleManager.ts b/src/renderers/GridStyleManager.ts index bc97604..ec95154 100644 --- a/src/renderers/GridStyleManager.ts +++ b/src/renderers/GridStyleManager.ts @@ -1,6 +1,16 @@ import { calendarConfig } from '../core/CalendarConfig'; import { ResourceCalendarData } from '../types/CalendarTypes'; +interface GridSettings { + hourHeight: number; + snapInterval: number; + dayStartHour: number; + dayEndHour: number; + workStartHour: number; + workEndHour: number; + fitToWidth?: boolean; +} + /** * GridStyleManager - Manages CSS variables and styling for the grid * Separated from GridManager to follow Single Responsibility Principle @@ -38,7 +48,7 @@ export class GridStyleManager { /** * Set time-related CSS variables */ - private setTimeVariables(root: HTMLElement, gridSettings: any): void { + private setTimeVariables(root: HTMLElement, gridSettings: GridSettings): void { root.style.setProperty('--hour-height', `${gridSettings.hourHeight}px`); root.style.setProperty('--minute-height', `${gridSettings.hourHeight / 60}px`); root.style.setProperty('--snap-interval', gridSettings.snapInterval.toString()); @@ -76,7 +86,7 @@ export class GridStyleManager { /** * Set column width based on fitToWidth setting */ - private setColumnWidth(root: HTMLElement, gridSettings: any): void { + private setColumnWidth(root: HTMLElement, gridSettings: GridSettings): void { if (gridSettings.fitToWidth) { root.style.setProperty('--day-column-min-width', '50px'); // Small min-width allows columns to fit available space } else { diff --git a/src/strategies/MonthViewStrategy.ts b/src/strategies/MonthViewStrategy.ts index c73642f..944503b 100644 --- a/src/strategies/MonthViewStrategy.ts +++ b/src/strategies/MonthViewStrategy.ts @@ -6,6 +6,7 @@ import { ViewStrategy, ViewContext, ViewLayoutConfig } from './ViewStrategy'; import { DateCalculator } from '../utils/DateCalculator'; import { calendarConfig } from '../core/CalendarConfig'; +import { CalendarEvent } from '../types/CalendarTypes'; export class MonthViewStrategy implements ViewStrategy { private dateCalculator: DateCalculator; @@ -113,7 +114,7 @@ export class MonthViewStrategy implements ViewStrategy { return dates; } - private renderMonthEvents(container: HTMLElement, events: any[]): void { + private renderMonthEvents(container: HTMLElement, events: CalendarEvent[]): void { // TODO: Implement month event rendering // Events will be small blocks in day cells } diff --git a/src/types/CalendarTypes.ts b/src/types/CalendarTypes.ts index 4e6d5e2..7ae63b5 100644 --- a/src/types/CalendarTypes.ts +++ b/src/types/CalendarTypes.ts @@ -80,7 +80,7 @@ export interface CalendarConfig { export interface EventLogEntry { type: string; - detail: any; + detail: unknown; timestamp: number; } @@ -94,7 +94,7 @@ export interface IEventBus { on(eventType: string, handler: EventListener, options?: AddEventListenerOptions): () => void; once(eventType: string, handler: EventListener): () => void; off(eventType: string, handler: EventListener): void; - emit(eventType: string, detail?: any): boolean; + emit(eventType: string, detail?: unknown): boolean; getEventLog(eventType?: string): EventLogEntry[]; setDebug(enabled: boolean): void; destroy(): void; diff --git a/src/types/DragDropTypes.ts b/src/types/DragDropTypes.ts new file mode 100644 index 0000000..1297d83 --- /dev/null +++ b/src/types/DragDropTypes.ts @@ -0,0 +1,47 @@ +/** + * Type definitions for drag and drop functionality + */ + +export interface MousePosition { + x: number; + y: number; + clientX?: number; + clientY?: number; +} + +export interface DragOffset { + x: number; + y: number; + offsetX?: number; + offsetY?: number; +} + +export interface DragState { + isDragging: boolean; + draggedElement: HTMLElement | null; + draggedClone: HTMLElement | null; + eventId: string | null; + startColumn: string | null; + currentColumn: string | null; + mouseOffset: DragOffset; +} + +export interface DragEndPosition { + column: string; + y: number; + snappedY: number; + time?: Date; +} + +export interface StackLinkData { + prev?: string; + next?: string; + isFirst?: boolean; + isLast?: boolean; +} + +export interface DragEventHandlers { + handleDragStart?(originalElement: HTMLElement, eventId: string, mouseOffset: DragOffset, column: string): void; + handleDragMove?(eventId: string, snappedY: number, column: string, mouseOffset: DragOffset): void; + handleDragEnd?(eventId: string, originalElement: HTMLElement, draggedClone: HTMLElement, finalColumn: string, finalY: number): void; +} \ No newline at end of file diff --git a/src/types/EventPayloadMap.ts b/src/types/EventPayloadMap.ts new file mode 100644 index 0000000..d9393ad --- /dev/null +++ b/src/types/EventPayloadMap.ts @@ -0,0 +1,177 @@ +import { CalendarEvent, CalendarView } from './CalendarTypes'; +import { + DragStartEventPayload, + DragMoveEventPayload, + DragEndEventPayload, + DragMouseEnterHeaderEventPayload, + DragMouseLeaveHeaderEventPayload, + HeaderReadyEventPayload +} from './EventTypes'; +import { CoreEvents } from '../constants/CoreEvents'; + +/** + * Complete type mapping for all calendar events + * This enables type-safe event emission and handling + */ +export interface CalendarEventPayloadMap { + // Lifecycle events + [CoreEvents.INITIALIZED]: { + initialized: boolean; + timestamp: number; + }; + [CoreEvents.READY]: undefined; + [CoreEvents.DESTROYED]: undefined; + + // View events + [CoreEvents.VIEW_CHANGED]: { + view: CalendarView; + previousView?: CalendarView; + }; + [CoreEvents.VIEW_RENDERED]: { + view: CalendarView; + }; + [CoreEvents.WORKWEEK_CHANGED]: { + settings: unknown; + }; + + // Navigation events + [CoreEvents.DATE_CHANGED]: { + date: Date; + view?: CalendarView; + }; + [CoreEvents.NAVIGATION_COMPLETED]: { + direction: 'previous' | 'next' | 'today'; + }; + [CoreEvents.PERIOD_INFO_UPDATE]: { + label: string; + startDate: Date; + endDate: Date; + }; + [CoreEvents.NAVIGATE_TO_EVENT]: { + eventId: string; + }; + + // Data events + [CoreEvents.DATA_LOADING]: undefined; + [CoreEvents.DATA_LOADED]: { + events: CalendarEvent[]; + count: number; + }; + [CoreEvents.DATA_ERROR]: { + error: Error; + }; + [CoreEvents.EVENTS_FILTERED]: { + filteredEvents: CalendarEvent[]; + }; + + // Grid events + [CoreEvents.GRID_RENDERED]: { + container: HTMLElement; + currentDate: Date; + startDate: Date; + endDate: Date; + columnCount: number; + }; + [CoreEvents.GRID_CLICKED]: { + column: string; + row: number; + }; + [CoreEvents.CELL_SELECTED]: { + cell: HTMLElement; + }; + + // Event management + [CoreEvents.EVENT_CREATED]: { + event: CalendarEvent; + }; + [CoreEvents.EVENT_UPDATED]: { + event: CalendarEvent; + previousData?: Partial; + }; + [CoreEvents.EVENT_DELETED]: { + eventId: string; + }; + [CoreEvents.EVENT_SELECTED]: { + eventId: string; + event?: CalendarEvent; + }; + + // System events + [CoreEvents.ERROR]: { + error: Error; + context?: string; + }; + [CoreEvents.REFRESH_REQUESTED]: { + view?: CalendarView; + date?: Date; + }; + + // Filter events + [CoreEvents.FILTER_CHANGED]: { + activeFilters: string[]; + visibleEvents: CalendarEvent[]; + }; + + // Rendering events + [CoreEvents.EVENTS_RENDERED]: { + eventCount: number; + }; + + // Drag events + 'drag:start': DragStartEventPayload; + 'drag:move': DragMoveEventPayload; + 'drag:end': DragEndEventPayload; + 'drag:mouseenter-header': DragMouseEnterHeaderEventPayload; + 'drag:mouseleave-header': DragMouseLeaveHeaderEventPayload; + 'drag:cancelled': { + reason: string; + }; + + // Header events + 'header:ready': HeaderReadyEventPayload; + 'header:height-changed': { + height: number; + rowCount: number; + }; + + // All-day events + 'allday:checkHeight': undefined; + 'allday:convert-to-allday': { + eventId: string; + element: HTMLElement; + }; + 'allday:convert-from-allday': { + eventId: string; + element: HTMLElement; + }; + + // Scroll events + 'scroll:sync': { + scrollTop: number; + source: string; + }; + 'scroll:to-hour': { + hour: number; + }; + + // Filter events + 'filter:updated': { + activeFilters: string[]; + visibleEvents: CalendarEvent[]; + }; + 'filter:search': { + query: string; + results: CalendarEvent[]; + }; +} + +// Helper type to get payload type for a specific event +export type EventPayload = CalendarEventPayloadMap[T]; + +// Type guard to check if an event has a payload +export function hasPayload( + eventType: T, + payload: unknown +): payload is CalendarEventPayloadMap[T] { + return payload !== undefined; +} \ No newline at end of file diff --git a/src/types/ManagerTypes.ts b/src/types/ManagerTypes.ts new file mode 100644 index 0000000..89f3582 --- /dev/null +++ b/src/types/ManagerTypes.ts @@ -0,0 +1,92 @@ +import { IEventBus, CalendarEvent, CalendarView } from './CalendarTypes'; +import { IManager } from '../interfaces/IManager'; + +/** + * Complete type definition for all managers returned by ManagerFactory + */ +export interface CalendarManagers { + eventManager: EventManager; + eventRenderer: EventRenderingService; + gridManager: GridManager; + scrollManager: ScrollManager; + navigationManager: unknown; // Avoid interface conflicts + viewManager: ViewManager; + calendarManager: CalendarManager; + dragDropManager: unknown; // Avoid interface conflicts + allDayManager: unknown; // Avoid interface conflicts +} + +export interface EventManager extends IManager { + loadData(): Promise; + getEvents(): CalendarEvent[]; + getEventsForPeriod(startDate: Date, endDate: Date): CalendarEvent[]; + getResourceData(): ResourceData | null; + navigateToEvent(eventId: string): boolean; +} + +export interface EventRenderingService extends IManager { + // EventRenderingService doesn't have a render method in current implementation +} + +export interface GridManager extends IManager { + render(): Promise; + getDisplayDates(): Date[]; + setResourceData(resourceData: import('./CalendarTypes').ResourceCalendarData | null): void; +} + +export interface ScrollManager extends IManager { + scrollTo(scrollTop: number): void; + scrollToHour(hour: number): void; +} + +// Use a more flexible interface that matches actual implementation +export interface NavigationManager extends IManager { + [key: string]: unknown; // Allow any properties from actual implementation +} + +export interface ViewManager extends IManager { + // ViewManager doesn't have setView in current implementation + getCurrentView?(): CalendarView; +} + +export interface CalendarManager extends IManager { + setView(view: CalendarView): void; + setCurrentDate(date: Date): void; + getInitializationReport(): InitializationReport; +} + +export interface DragDropManager extends IManager { + // DragDropManager has different interface in current implementation +} + +export interface AllDayManager extends IManager { + [key: string]: unknown; // Allow any properties from actual implementation +} + +export interface ResourceData { + resources: Resource[]; + assignments?: ResourceAssignment[]; +} + +export interface Resource { + id: string; + name: string; + type?: string; + color?: string; +} + +export interface ResourceAssignment { + resourceId: string; + eventId: string; +} + +export interface InitializationReport { + initialized: boolean; + timestamp: number; + managers: { + [key: string]: { + initialized: boolean; + error?: string; + }; + }; +} \ No newline at end of file diff --git a/src/utils/PositionUtils.ts b/src/utils/PositionUtils.ts index 1718033..b8281b3 100644 --- a/src/utils/PositionUtils.ts +++ b/src/utils/PositionUtils.ts @@ -1,5 +1,5 @@ -import { calendarConfig } from '../core/CalendarConfig.js'; -import { DateCalculator } from './DateCalculator.js'; +import { calendarConfig } from '../core/CalendarConfig'; +import { DateCalculator } from './DateCalculator'; /** * PositionUtils - Static positioning utilities using singleton calendarConfig