/* Offline-Queue für Foto-Uploads. * Wenn der Upload fehlschlägt (offline), wird er in IndexedDB abgelegt * und beim nächsten Online-Event automatisch nachgesendet. */ (function () { let syncing = false; async function enqueuePhoto(orderId, fileBlob, filename) { // Blob → ArrayBuffer für IndexedDB-Speicherung const buf = await fileBlob.arrayBuffer(); const id = await idb.queuePush({ type: 'photo', order_id: orderId, filename, mime: fileBlob.type || 'image/jpeg', data: buf, created: Date.now(), }); updateBadge(); return id; } async function syncQueue() { if (syncing) return; if (!navigator.onLine) return; syncing = true; try { const items = await idb.queueAll(); for (const it of items) { try { if (it.type === 'photo') { const blob = new Blob([it.data], { type: it.mime }); await api.uploadOrderPhoto(it.order_id, blob, it.filename); } await idb.queueDelete(it.id); } catch (e) { console.warn('Sync failed for item', it.id, e); // Nicht weiter versuchen wenn ein Item failed break; } } } finally { syncing = false; updateBadge(); } } async function updateBadge() { const items = await idb.queueAll(); const badge = document.getElementById('status-badge'); if (!badge) return; if (!navigator.onLine) { badge.textContent = items.length ? '🔴 ' + items.length : '🔴'; badge.title = items.length + ' Uploads warten'; } else if (items.length) { badge.textContent = '🟡 ' + items.length; badge.title = items.length + ' werden synchronisiert'; } else { badge.textContent = '🟢'; badge.title = 'Online'; } } window.addEventListener('online', () => { updateBadge(); syncQueue(); }); window.addEventListener('offline', updateBadge); document.addEventListener('DOMContentLoaded', () => { updateBadge(); if (navigator.onLine) syncQueue(); // Periodischer Sync alle 30s setInterval(() => { if (navigator.onLine) syncQueue(); }, 30000); }); window.offline = { enqueuePhoto, syncQueue, updateBadge }; })();