Implements offline-first calendar sync infrastructure

Adds IndexedDB and operation queue for robust offline synchronization
Introduces SyncManager to handle background data synchronization
Supports local event operations with automatic remote sync queuing

Enhances application reliability and user experience in low/no connectivity scenarios
This commit is contained in:
Janus C. H. Knudsen 2025-11-05 00:37:57 +01:00
parent 9c765b35ab
commit e7011526e3
20 changed files with 3822 additions and 57 deletions

View file

@ -127,13 +127,13 @@ export class AllDayManager {
});
// Listen for header ready - when dates are populated with period data
eventBus.on('header:ready', (event: Event) => {
eventBus.on('header:ready', async (event: Event) => {
let headerReadyEventPayload = (event as CustomEvent<IHeaderReadyEventPayload>).detail;
let startDate = new Date(headerReadyEventPayload.headerElements.at(0)!.date);
let endDate = new Date(headerReadyEventPayload.headerElements.at(-1)!.date);
let events: ICalendarEvent[] = this.eventManager.getEventsForPeriod(startDate, endDate);
let events: ICalendarEvent[] = await this.eventManager.getEventsForPeriod(startDate, endDate);
// Filter for all-day events
const allDayEvents = events.filter(event => event.allDay);
@ -380,7 +380,7 @@ export class AllDayManager {
}
private handleDragEnd(dragEndEvent: IDragEndEventPayload): void {
private async handleDragEnd(dragEndEvent: IDragEndEventPayload): Promise<void> {
const getEventDurationDays = (start: string | undefined, end: string | undefined): number => {
@ -496,6 +496,15 @@ export class AllDayManager {
// 7. Apply highlight class to show the dropped event with highlight color
dragEndEvent.draggedClone.classList.add('highlight');
// 8. CRITICAL FIX: Update event in repository to mark as allDay=true
// This ensures EventManager's repository has correct state
// Without this, the event will reappear in grid on re-render
await this.eventManager.updateEvent(eventId, {
start: newStartDate,
end: newEndDate,
allDay: true
});
this.fadeOutAndRemove(dragEndEvent.originalElement);
this.checkAndAnimateAllDayHeight();