import { ICalendarEvent, EntityType, IEventBus } from '../../types/CalendarTypes'; import { EventStore } from './EventStore'; import { EventSerialization } from './EventSerialization'; import { BaseEntityService } from '../BaseEntityService'; import { IndexedDBContext } from '../IndexedDBContext'; /** * EventService - CRUD operations for calendar events in IndexedDB * * Extends BaseEntityService for shared CRUD and sync logic. * Provides event-specific query methods. */ export class EventService extends BaseEntityService { readonly storeName = EventStore.STORE_NAME; readonly entityType: EntityType = 'Event'; constructor(context: IndexedDBContext, eventBus: IEventBus) { super(context, eventBus); } protected serialize(event: ICalendarEvent): unknown { return EventSerialization.serialize(event); } protected deserialize(data: unknown): ICalendarEvent { return EventSerialization.deserialize(data as Record); } /** * Get events within a date range */ async getByDateRange(start: Date, end: Date): Promise { return new Promise((resolve, reject) => { const transaction = this.db.transaction([this.storeName], 'readonly'); const store = transaction.objectStore(this.storeName); const index = store.index('start'); const range = IDBKeyRange.lowerBound(start.toISOString()); const request = index.getAll(range); request.onsuccess = () => { const data = request.result as unknown[]; const events = data .map(item => this.deserialize(item)) .filter(event => event.start <= end); resolve(events); }; request.onerror = () => { reject(new Error(`Failed to get events by date range: ${request.error}`)); }; }); } /** * Get events for a specific resource */ async getByResource(resourceId: string): Promise { return new Promise((resolve, reject) => { const transaction = this.db.transaction([this.storeName], 'readonly'); const store = transaction.objectStore(this.storeName); const index = store.index('resourceId'); const request = index.getAll(resourceId); request.onsuccess = () => { const data = request.result as unknown[]; const events = data.map(item => this.deserialize(item)); resolve(events); }; request.onerror = () => { reject(new Error(`Failed to get events for resource ${resourceId}: ${request.error}`)); }; }); } /** * Get events for a resource within a date range */ async getByResourceAndDateRange(resourceId: string, start: Date, end: Date): Promise { const resourceEvents = await this.getByResource(resourceId); return resourceEvents.filter(event => event.start >= start && event.start <= end); } }