// Offline storage system for PWA using IndexedDB interface UserProfile { id: string; name: string; phone: string; organization?: string; role: 'engineer' | 'student' | 'researcher' | 'government' | 'farmer' | 'consultant'; lastLogin: Date; createdAt: Date; } interface Project { id: number; name: string; description?: string; type: string; location?: string; status: string; data: any; createdAt: Date; updatedAt: Date; } interface GovernmentReport { id: number; projectId?: number; reportType: string; title: string; content: any; status: string; generatedData: any; createdAt: Date; } interface CropPlan { id: number; projectId?: number; farmName: string; location: string; soilType: string; climate: string; area: number; cropRotation: any; waterRequirement: any; fertilizerPlan: any; season: string; createdAt: Date; } interface CoastalProject { id: number; projectId?: number; siteName: string; coordinates: string; coastlineLength?: number; mangroveData: any; erosionRisk: any; crzMapping: any; protectionMeasures: any; createdAt: Date; } interface CommunityPost { id: number; title: string; description: string; category: string; projectData?: any; tags: string[]; likes: number; isPublic: boolean; createdAt: Date; } class OfflineStorage { private dbName = 'PrithviGuardianDB'; private version = 1; private db: IDBDatabase | null = null; async init(): Promise { return new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, this.version); request.onerror = () => reject(request.error); request.onsuccess = () => { this.db = request.result; resolve(); }; request.onupgradeneeded = (event) => { const db = (event.target as IDBOpenDBRequest).result; // Create object stores if (!db.objectStoreNames.contains('projects')) { const projectStore = db.createObjectStore('projects', { keyPath: 'id', autoIncrement: true }); projectStore.createIndex('type', 'type', { unique: false }); } if (!db.objectStoreNames.contains('governmentReports')) { const reportStore = db.createObjectStore('governmentReports', { keyPath: 'id', autoIncrement: true }); reportStore.createIndex('reportType', 'reportType', { unique: false }); } if (!db.objectStoreNames.contains('cropPlans')) { const cropStore = db.createObjectStore('cropPlans', { keyPath: 'id', autoIncrement: true }); cropStore.createIndex('season', 'season', { unique: false }); } if (!db.objectStoreNames.contains('coastalProjects')) { const coastalStore = db.createObjectStore('coastalProjects', { keyPath: 'id', autoIncrement: true }); } if (!db.objectStoreNames.contains('communityPosts')) { const communityStore = db.createObjectStore('communityPosts', { keyPath: 'id', autoIncrement: true }); communityStore.createIndex('category', 'category', { unique: false }); } }; }); } private async getStore(storeName: string, mode: IDBTransactionMode = 'readonly'): Promise { if (!this.db) await this.init(); const transaction = this.db!.transaction([storeName], mode); return transaction.objectStore(storeName); } // Projects async getProjects(): Promise { const store = await this.getStore('projects'); return new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result || []); request.onerror = () => reject(request.error); }); } async createProject(project: Omit): Promise { const store = await this.getStore('projects', 'readwrite'); const newProject = { ...project, createdAt: new Date(), updatedAt: new Date() }; return new Promise((resolve, reject) => { const request = store.add(newProject); request.onsuccess = () => { resolve({ ...newProject, id: request.result as number }); }; request.onerror = () => reject(request.error); }); } // Government Reports async getGovernmentReports(): Promise { const store = await this.getStore('governmentReports'); return new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result || []); request.onerror = () => reject(request.error); }); } async createGovernmentReport(report: Omit): Promise { const store = await this.getStore('governmentReports', 'readwrite'); const newReport = { ...report, createdAt: new Date() }; return new Promise((resolve, reject) => { const request = store.add(newReport); request.onsuccess = () => { resolve({ ...newReport, id: request.result as number }); }; request.onerror = () => reject(request.error); }); } // Crop Plans async getCropPlans(): Promise { const store = await this.getStore('cropPlans'); return new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result || []); request.onerror = () => reject(request.error); }); } async createCropPlan(plan: Omit): Promise { const store = await this.getStore('cropPlans', 'readwrite'); const newPlan = { ...plan, createdAt: new Date() }; return new Promise((resolve, reject) => { const request = store.add(newPlan); request.onsuccess = () => { resolve({ ...newPlan, id: request.result as number }); }; request.onerror = () => reject(request.error); }); } // Coastal Projects async getCoastalProjects(): Promise { const store = await this.getStore('coastalProjects'); return new Promise((resolve, reject) => { const request = store.getAll(); request.onsuccess = () => resolve(request.result || []); request.onerror = () => reject(request.error); }); } async createCoastalProject(project: Omit): Promise { const store = await this.getStore('coastalProjects', 'readwrite'); const newProject = { ...project, createdAt: new Date() }; return new Promise((resolve, reject) => { const request = store.add(newProject); request.onsuccess = () => { resolve({ ...newProject, id: request.result as number }); }; request.onerror = () => reject(request.error); }); } // Community Posts async getCommunityPosts(category?: string): Promise { const store = await this.getStore('communityPosts'); return new Promise((resolve, reject) => { let request: IDBRequest; if (category && category !== 'all') { const index = store.index('category'); request = index.getAll(category); } else { request = store.getAll(); } request.onsuccess = () => resolve(request.result || []); request.onerror = () => reject(request.error); }); } async createCommunityPost(post: Omit): Promise { const store = await this.getStore('communityPosts', 'readwrite'); const newPost = { ...post, likes: 0, createdAt: new Date() }; return new Promise((resolve, reject) => { const request = store.add(newPost); request.onsuccess = () => { resolve({ ...newPost, id: request.result as number }); }; request.onerror = () => reject(request.error); }); } async likeCommunityPost(id: number): Promise { const store = await this.getStore('communityPosts', 'readwrite'); return new Promise((resolve, reject) => { const getRequest = store.get(id); getRequest.onsuccess = () => { const post = getRequest.result; if (post) { post.likes = (post.likes || 0) + 1; const updateRequest = store.put(post); updateRequest.onsuccess = () => resolve(); updateRequest.onerror = () => reject(updateRequest.error); } else { resolve(); } }; getRequest.onerror = () => reject(getRequest.error); }); } } export const offlineStorage = new OfflineStorage();