// Main entry point for Calendar Plantempus import { Container } from '@novadi/core'; import { eventBus } from './core/EventBus'; import { ConfigManager } from './configurations/ConfigManager'; import { Configuration } from './configurations/CalendarConfig'; import { URLManager } from './utils/URLManager'; import { ICalendarEvent, IEventBus } from './types/CalendarTypes'; // Import all managers import { EventManager } from './managers/EventManager'; import { EventRenderingService } from './renderers/EventRendererManager'; import { GridManager } from './managers/GridManager'; import { ScrollManager } from './managers/ScrollManager'; import { NavigationManager } from './managers/NavigationManager'; import { NavigationButtons } from './components/NavigationButtons'; import { ViewSelector } from './components/ViewSelector'; import { CalendarManager } from './managers/CalendarManager'; import { DragDropManager } from './managers/DragDropManager'; import { AllDayManager } from './managers/AllDayManager'; import { ResizeHandleManager } from './managers/ResizeHandleManager'; import { EdgeScrollManager } from './managers/EdgeScrollManager'; import { HeaderManager } from './managers/HeaderManager'; import { WorkweekPresets } from './components/WorkweekPresets'; // Import repositories and storage import { MockEventRepository } from './repositories/MockEventRepository'; import { MockBookingRepository } from './repositories/MockBookingRepository'; import { MockCustomerRepository } from './repositories/MockCustomerRepository'; import { MockResourceRepository } from './repositories/MockResourceRepository'; import { MockAuditRepository } from './repositories/MockAuditRepository'; import { IApiRepository } from './repositories/IApiRepository'; import { IAuditEntry } from './types/AuditTypes'; import { ApiEventRepository } from './repositories/ApiEventRepository'; import { ApiBookingRepository } from './repositories/ApiBookingRepository'; import { ApiCustomerRepository } from './repositories/ApiCustomerRepository'; import { ApiResourceRepository } from './repositories/ApiResourceRepository'; import { IndexedDBContext } from './storage/IndexedDBContext'; import { IStore } from './storage/IStore'; import { AuditStore } from './storage/audit/AuditStore'; import { AuditService } from './storage/audit/AuditService'; import { BookingStore } from './storage/bookings/BookingStore'; import { CustomerStore } from './storage/customers/CustomerStore'; import { ResourceStore } from './storage/resources/ResourceStore'; import { EventStore } from './storage/events/EventStore'; import { IEntityService } from './storage/IEntityService'; import { EventService } from './storage/events/EventService'; import { BookingService } from './storage/bookings/BookingService'; import { CustomerService } from './storage/customers/CustomerService'; import { ResourceService } from './storage/resources/ResourceService'; // Import workers import { SyncManager } from './workers/SyncManager'; import { DataSeeder } from './workers/DataSeeder'; // Import renderers import { DateHeaderRenderer, type IHeaderRenderer } from './renderers/DateHeaderRenderer'; import { DateColumnRenderer, type IColumnRenderer } from './renderers/ColumnRenderer'; import { DateEventRenderer, type IEventRenderer } from './renderers/EventRenderer'; import { AllDayEventRenderer } from './renderers/AllDayEventRenderer'; import { GridRenderer } from './renderers/GridRenderer'; import { WeekInfoRenderer } from './renderers/WeekInfoRenderer'; // Import utilities and services import { DateService } from './utils/DateService'; import { TimeFormatter } from './utils/TimeFormatter'; import { PositionUtils } from './utils/PositionUtils'; import { AllDayLayoutEngine } from './utils/AllDayLayoutEngine'; import { WorkHoursManager } from './managers/WorkHoursManager'; import { EventStackManager } from './managers/EventStackManager'; import { EventLayoutCoordinator } from './managers/EventLayoutCoordinator'; import { IColumnDataSource } from './types/ColumnDataSource'; import { DateColumnDataSource } from './datasources/DateColumnDataSource'; import { ResourceColumnDataSource } from './datasources/ResourceColumnDataSource'; import { ResourceHeaderRenderer } from './renderers/ResourceHeaderRenderer'; import { ResourceColumnRenderer } from './renderers/ResourceColumnRenderer'; import { IBooking } from './types/BookingTypes'; import { ICustomer } from './types/CustomerTypes'; import { IResource } from './types/ResourceTypes'; /** * Handle deep linking functionality after managers are initialized */ async function handleDeepLinking(eventManager: EventManager, urlManager: URLManager): Promise { try { const eventId = urlManager.parseEventIdFromURL(); if (eventId) { console.log(`Deep linking to event ID: ${eventId}`); // Wait a bit for managers to be fully ready setTimeout(async () => { const success = await eventManager.navigateToEvent(eventId); if (!success) { console.warn(`Deep linking failed: Event with ID ${eventId} not found`); } }, 500); } } catch (error) { console.warn('Deep linking failed:', error); } } /** * Initialize the calendar application using NovaDI */ async function initializeCalendar(): Promise { try { // Load configuration from JSON const config = await ConfigManager.load(); // Create NovaDI container const container = new Container(); const builder = container.builder(); // Enable debug mode for development eventBus.setDebug(true); // Bind core services as instances builder.registerInstance(eventBus).as(); // Register configuration instance builder.registerInstance(config).as(); // Register storage stores (IStore implementations) // Open/Closed Principle: Adding new entity only requires adding one line here builder.registerType(BookingStore).as(); builder.registerType(CustomerStore).as(); builder.registerType(ResourceStore).as(); builder.registerType(EventStore).as(); builder.registerType(AuditStore).as(); // Register storage and repository services builder.registerType(IndexedDBContext).as(); // Register Mock repositories (development/testing - load from JSON files) // Each entity type has its own Mock repository implementing IApiRepository builder.registerType(MockEventRepository).as>(); builder.registerType(MockBookingRepository).as>(); builder.registerType(MockCustomerRepository).as>(); builder.registerType(MockResourceRepository).as>(); builder.registerType(MockAuditRepository).as>(); let calendarMode = 'resource' ; // Register DataSource and HeaderRenderer based on mode if (calendarMode === 'resource') { builder.registerType(ResourceColumnDataSource).as(); builder.registerType(ResourceHeaderRenderer).as(); } else { builder.registerType(DateColumnDataSource).as(); builder.registerType(DateHeaderRenderer).as(); } // Register entity services (sync status management) // Open/Closed Principle: Adding new entity only requires adding one line here builder.registerType(EventService).as>(); builder.registerType(EventService).as(); builder.registerType(BookingService).as>(); builder.registerType(CustomerService).as>(); builder.registerType(ResourceService).as>(); builder.registerType(ResourceService).as(); builder.registerType(AuditService).as(); // Register workers builder.registerType(SyncManager).as(); builder.registerType(DataSeeder).as(); // Register renderers // Note: IHeaderRenderer and IColumnRenderer are registered above based on calendarMode if (calendarMode === 'resource') { builder.registerType(ResourceColumnRenderer).as(); } else { builder.registerType(DateColumnRenderer).as(); } builder.registerType(DateEventRenderer).as(); // Register core services and utilities builder.registerType(DateService).as(); builder.registerType(EventStackManager).as(); builder.registerType(EventLayoutCoordinator).as(); builder.registerType(WorkHoursManager).as(); builder.registerType(URLManager).as(); builder.registerType(TimeFormatter).as(); builder.registerType(PositionUtils).as(); // Note: AllDayLayoutEngine is instantiated per-operation with specific dates, not a singleton builder.registerType(WeekInfoRenderer).as(); builder.registerType(AllDayEventRenderer).as(); builder.registerType(EventRenderingService).as(); builder.registerType(GridRenderer).as(); builder.registerType(GridManager).as(); builder.registerType(ScrollManager).as(); builder.registerType(NavigationManager).as(); builder.registerType(NavigationButtons).as(); builder.registerType(ViewSelector).as(); builder.registerType(DragDropManager).as(); builder.registerType(AllDayManager).as(); builder.registerType(ResizeHandleManager).as(); builder.registerType(EdgeScrollManager).as(); builder.registerType(HeaderManager).as(); builder.registerType(CalendarManager).as(); builder.registerType(WorkweekPresets).as(); builder.registerType(ConfigManager).as(); builder.registerType(EventManager).as(); // Build the container const app = builder.build(); // Initialize database and seed data BEFORE initializing managers const indexedDBContext = app.resolveType(); await indexedDBContext.initialize(); const dataSeeder = app.resolveType(); await dataSeeder.seedIfEmpty(); // Get managers from container const eb = app.resolveType(); const calendarManager = app.resolveType(); const eventManager = app.resolveType(); const resizeHandleManager = app.resolveType(); const headerManager = app.resolveType(); const dragDropManager = app.resolveType(); const viewSelectorManager = app.resolveType(); const navigationManager = app.resolveType(); const navigationButtonsManager = app.resolveType(); const edgeScrollManager = app.resolveType(); const allDayManager = app.resolveType(); const urlManager = app.resolveType(); const workweekPresetsManager = app.resolveType(); const configManager = app.resolveType(); // Initialize managers await calendarManager.initialize?.(); await resizeHandleManager.initialize?.(); // Resolve AuditService (starts listening for entity events) const auditService = app.resolveType(); // Resolve SyncManager (starts background sync automatically) const syncManager = app.resolveType(); // Handle deep linking after managers are initialized await handleDeepLinking(eventManager, urlManager); // Expose to window for debugging (with proper typing) (window as Window & { calendarDebug?: { eventBus: typeof eventBus; app: typeof app; calendarManager: typeof calendarManager; eventManager: typeof eventManager; workweekPresetsManager: typeof workweekPresetsManager; auditService: typeof auditService; syncManager: typeof syncManager; }; }).calendarDebug = { eventBus, app, calendarManager, eventManager, workweekPresetsManager, auditService, syncManager, }; } catch (error) { throw error; } } // Initialize when DOM is ready - now handles async properly if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { initializeCalendar().catch(error => { console.error('Calendar initialization failed:', error); }); }); } else { initializeCalendar().catch(error => { console.error('Calendar initialization failed:', error); }); }