Calendar/src/v2/managers/EventPersistenceManager.ts
Janus C. H. Knudsen f670598e7a Refactor event handling with SwpEvent wrapper
Introduces SwpEvent class to centralize event element data and calculations

Improves drag and resize event handling by extracting common logic
Simplifies calculation of event start/end times from element positions
Enhances type safety and reduces code complexity in event managers

Removes direct pixel/minute calculations from multiple managers
2025-12-11 22:45:33 +01:00

101 lines
3.4 KiB
TypeScript

/**
* 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<void> => {
const payload = (e as CustomEvent<IDragEndPayload>).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<void> => {
const payload = (e as CustomEvent<IResizeEndPayload>).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);
};
}