This commit is contained in:
2026-02-22 14:38:53 -06:00
parent bec656b105
commit a73de4a4fa
47 changed files with 4290 additions and 3 deletions

View File

@@ -0,0 +1,230 @@
/**
* IndexedDB Wrapper for Offline Colaboraciones
* Stores pending colaboraciones when offline using GUID-based IDs
*/
const ColaboracionesOfflineDB = {
dbName: 'ColaboracionesOfflineDB',
version: 1,
storeName: 'colaboraciones',
/**
* Initialize the database
*/
async init() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Create object store if it doesn't exist
if (!db.objectStoreNames.contains(this.storeName)) {
const objectStore = db.createObjectStore(this.storeName, {
keyPath: 'id' // GUID generated client-side
});
// Indexes for querying
objectStore.createIndex('syncStatus', 'syncStatus', { unique: false });
objectStore.createIndex('timestamp', 'timestamp', { unique: false });
objectStore.createIndex('updatedAt', 'updatedAt', { unique: false });
objectStore.createIndex('miembroId', 'miembroId', { unique: false });
}
};
});
},
/**
* Generate a GUID (v4 UUID)
*/
generateGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
/**
* Add a new colaboracion to offline queue
*/
async addColaboracion(colaboracionData) {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
// Prepare record with GUID and sync metadata
const record = {
id: this.generateGuid(), // GUID generated client-side
miembroId: colaboracionData.miembroId,
mesInicial: colaboracionData.mesInicial,
anioInicial: colaboracionData.anioInicial,
mesFinal: colaboracionData.mesFinal,
anioFinal: colaboracionData.anioFinal,
montoTotal: colaboracionData.montoTotal,
observaciones: colaboracionData.observaciones || '',
tiposSeleccionados: colaboracionData.tiposSeleccionados || [],
tipoPrioritario: colaboracionData.tipoPrioritario || null,
registradoPor: colaboracionData.registradoPor || 'Usuario',
syncStatus: 'pending', // pending, syncing, synced, failed
timestamp: new Date().toISOString(),
updatedAt: new Date().toISOString(),
retryCount: 0
};
const request = store.add(record);
request.onsuccess = () => {
console.log('[OfflineDB] Colaboración guardada con ID:', record.id);
resolve(record);
};
request.onerror = () => {
console.error('[OfflineDB] Error al guardar:', request.error);
reject(request.error);
};
});
},
/**
* Get all pending colaboraciones
*/
async getPending() {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const index = store.index('syncStatus');
const request = index.getAll('pending');
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
},
/**
* Get all colaboraciones (any status)
*/
async getAll() {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const request = store.getAll();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
},
/**
* Update sync status of a colaboracion
*/
async updateSyncStatus(id, status, retryCount = 0) {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
const getRequest = store.get(id);
getRequest.onsuccess = () => {
const record = getRequest.result;
if (record) {
record.syncStatus = status;
record.retryCount = retryCount;
record.lastSyncAttempt = new Date().toISOString();
const updateRequest = store.put(record);
updateRequest.onsuccess = () => resolve(record);
updateRequest.onerror = () => reject(updateRequest.error);
} else {
reject(new Error('Record not found'));
}
};
getRequest.onerror = () => reject(getRequest.error);
});
},
/**
* Remove a colaboracion by ID (after successful sync)
*/
async remove(id) {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
const request = store.delete(id);
request.onsuccess = () => {
console.log('[OfflineDB] Colaboración eliminada:', id);
resolve();
};
request.onerror = () => reject(request.error);
});
},
/**
* Get count of pending colaboraciones
*/
async getPendingCount() {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const index = store.index('syncStatus');
const request = index.count('pending');
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
},
/**
* Clear all records (use with caution)
*/
async clearAll() {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
const request = store.clear();
request.onsuccess = () => {
console.log('[OfflineDB] All records cleared');
resolve();
};
request.onerror = () => reject(request.error);
});
},
/**
* Get a specific colaboracion by ID
*/
async getById(id) {
const db = await this.init();
return new Promise((resolve, reject) => {
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const request = store.get(id);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
};
// Initialize database when script loads
ColaboracionesOfflineDB.init().catch(error => {
console.error('[OfflineDB] Initialization failed:', error);
});