/** * EventPersistenceManager - Persists event changes to IndexedDB * * Listens to drag/resize events and updates IndexedDB via EventService. * This bridges the gap between UI interactions and data persistence. */ import { ICalendarEvent, IEventBus, IEventUpdatedPayload } from '../types/CalendarTypes'; import { EventService } from '../storage/events/EventService'; import { DateService } from '../core/DateService'; import { CoreEvents } from '../constants/CoreEvents'; import { IDragEndPayload } from '../types/DragTypes'; import { IResizeEndPayload } from '../types/ResizeTypes'; export class EventPersistenceManager { constructor( private eventService: EventService, private eventBus: IEventBus, private dateService: DateService ) { this.setupListeners(); } private setupListeners(): void { this.eventBus.on(CoreEvents.EVENT_DRAG_END, this.handleDragEnd); this.eventBus.on(CoreEvents.EVENT_RESIZE_END, this.handleResizeEnd); } /** * Handle drag end - update event position in IndexedDB */ private handleDragEnd = async (e: Event): Promise => { const payload = (e as CustomEvent).detail; const { swpEvent } = payload; // Get existing event to merge with const event = await this.eventService.get(swpEvent.eventId); if (!event) { console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`); return; } // Update and save - start/end already calculated in SwpEvent const updatedEvent: ICalendarEvent = { ...event, start: swpEvent.start, end: swpEvent.end, resourceId: swpEvent.resourceId ?? event.resourceId, syncStatus: 'pending' }; await this.eventService.save(updatedEvent); // Emit EVENT_UPDATED for EventRenderer to re-render affected columns const targetDateKey = this.dateService.getDateKey(swpEvent.start); const updatePayload: IEventUpdatedPayload = { eventId: updatedEvent.id, sourceDateKey: payload.sourceDateKey, sourceResourceId: payload.sourceResourceId, targetDateKey, targetResourceId: swpEvent.resourceId }; this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload); }; /** * Handle resize end - update event duration in IndexedDB */ private handleResizeEnd = async (e: Event): Promise => { const payload = (e as CustomEvent).detail; const { swpEvent } = payload; // Get existing event to merge with const event = await this.eventService.get(swpEvent.eventId); if (!event) { console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`); return; } // Update and save - end already calculated in SwpEvent const updatedEvent: ICalendarEvent = { ...event, end: swpEvent.end, syncStatus: 'pending' }; await this.eventService.save(updatedEvent); // Emit EVENT_UPDATED for EventRenderer to re-render the column // Resize stays in same column, so source and target are the same const dateKey = this.dateService.getDateKey(swpEvent.start); const updatePayload: IEventUpdatedPayload = { eventId: updatedEvent.id, sourceDateKey: dateKey, sourceResourceId: swpEvent.resourceId, targetDateKey: dateKey, targetResourceId: swpEvent.resourceId }; this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload); }; }