import type { Presentation, PresentationMetadata, CreatePresentationRequest } from '../types/presentation'; const DB_NAME = 'SlideshareDB'; const DB_VERSION = 1; const PRESENTATIONS_STORE = 'presentations'; /** * Initialize IndexedDB database */ export const initializeDB = (): Promise => { return new Promise((resolve, reject) => { const request = indexedDB.open(DB_NAME, DB_VERSION); request.onerror = () => { reject(new Error('Failed to open IndexedDB database')); }; request.onsuccess = () => { resolve(request.result); }; request.onupgradeneeded = (event) => { const db = (event.target as IDBOpenDBRequest).result; // Create presentations object store if (!db.objectStoreNames.contains(PRESENTATIONS_STORE)) { const store = db.createObjectStore(PRESENTATIONS_STORE, { keyPath: 'metadata.id' }); // Create indexes for efficient querying store.createIndex('name', 'metadata.name', { unique: false }); store.createIndex('theme', 'metadata.theme', { unique: false }); store.createIndex('createdAt', 'metadata.createdAt', { unique: false }); store.createIndex('updatedAt', 'metadata.updatedAt', { unique: false }); } }; }); }; /** * Generate a unique ID for presentations */ const generatePresentationId = (): string => { return `presentation_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; }; /** * Create a new presentation */ export const createPresentation = async (request: CreatePresentationRequest): Promise => { const db = await initializeDB(); const now = new Date().toISOString(); const presentation: Presentation = { metadata: { id: generatePresentationId(), name: request.name, description: request.description, theme: request.theme, aspectRatio: request.aspectRatio, createdAt: now, updatedAt: now }, slides: [] }; return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readwrite'); const store = transaction.objectStore(PRESENTATIONS_STORE); const request = store.add(presentation); request.onerror = () => { reject(new Error('Failed to create presentation')); }; request.onsuccess = () => { resolve(presentation); }; transaction.onerror = () => { reject(new Error('Transaction failed while creating presentation')); }; }); }; /** * Get all presentations */ export const getAllPresentations = async (): Promise => { const db = await initializeDB(); return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readonly'); const store = transaction.objectStore(PRESENTATIONS_STORE); const request = store.getAll(); request.onerror = () => { reject(new Error('Failed to retrieve presentations')); }; request.onsuccess = () => { // Sort by creation date (newest first) const presentations = request.result.sort((a: Presentation, b: Presentation) => new Date(b.metadata.createdAt).getTime() - new Date(a.metadata.createdAt).getTime() ); resolve(presentations); }; }); }; /** * Get a presentation by ID */ export const getPresentationById = async (id: string): Promise => { const db = await initializeDB(); return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readonly'); const store = transaction.objectStore(PRESENTATIONS_STORE); const request = store.get(id); request.onerror = () => { reject(new Error('Failed to retrieve presentation')); }; request.onsuccess = () => { resolve(request.result || null); }; }); }; /** * Update a presentation */ export const updatePresentation = async (presentation: Presentation): Promise => { const db = await initializeDB(); // Update the updatedAt timestamp presentation.metadata.updatedAt = new Date().toISOString(); return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readwrite'); const store = transaction.objectStore(PRESENTATIONS_STORE); const request = store.put(presentation); request.onerror = () => { reject(new Error('Failed to update presentation')); }; request.onsuccess = () => { resolve(presentation); }; }); }; /** * Delete a presentation */ export const deletePresentation = async (id: string): Promise => { const db = await initializeDB(); return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readwrite'); const store = transaction.objectStore(PRESENTATIONS_STORE); const request = store.delete(id); request.onerror = () => { reject(new Error('Failed to delete presentation')); }; request.onsuccess = () => { resolve(); }; }); }; /** * Get presentations by theme */ export const getPresentationsByTheme = async (theme: string): Promise => { const db = await initializeDB(); return new Promise((resolve, reject) => { const transaction = db.transaction([PRESENTATIONS_STORE], 'readonly'); const store = transaction.objectStore(PRESENTATIONS_STORE); const index = store.index('theme'); const request = index.getAll(theme); request.onerror = () => { reject(new Error('Failed to retrieve presentations by theme')); }; request.onsuccess = () => { // Sort by creation date (newest first) const presentations = request.result.sort((a: Presentation, b: Presentation) => new Date(b.metadata.createdAt).getTime() - new Date(a.metadata.createdAt).getTime() ); resolve(presentations); }; }); }; /** * Get presentation metadata only (for listing views) */ export const getPresentationMetadata = async (): Promise => { const presentations = await getAllPresentations(); return presentations.map(p => p.metadata); };