baustelle-pwa/lib/idb.js
Eduard Wisch 7c0aefa793
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
feat: Initiales Release Baustelle PWA v1.0.0 [deploy]
Mobile Progressive Web App für Baustellen-Doku, spricht die REST-API
des Dolibarr-Bericht-Moduls.

MVP-Features:
- Vanilla JavaScript, kein Build-Step nötig
- Login mit Dolibarr-Credentials → JWT (7 Tage)
- Auftragsliste mit Suche und Multi-User-Filter
- Auftragsdetail mit Kunde, Adresse, Click-to-Call
- Foto-Aufnahme via Kamera oder Galerie (multiple)
- Clientseitige Bildverkleinerung (max 2000px, JPEG q=0.85)
- Offline-Queue in IndexedDB für Uploads ohne Netz
- Auto-Sync bei Online-Event mit Status-Badge
- Service Worker für App-Shell-Cache
- PWA-installierbar (Manifest, Icons, Theme-Color)

Hosting: awl.data-it-solution.de/baustelle/ via Apache-Alias

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:50:01 +02:00

89 lines
2.9 KiB
JavaScript

/* Mini IndexedDB Wrapper für die PWA.
* Speichert: Auth-Token, Offline-Queue für Uploads.
*/
(function () {
const DB_NAME = 'baustelle-pwa-v1';
const DB_VERSION = 1;
let dbPromise = null;
function open() {
if (dbPromise) return dbPromise;
dbPromise = new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onupgradeneeded = () => {
const db = req.result;
if (!db.objectStoreNames.contains('kv')) {
db.createObjectStore('kv');
}
if (!db.objectStoreNames.contains('queue')) {
db.createObjectStore('queue', { keyPath: 'id', autoIncrement: true });
}
};
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
return dbPromise;
}
async function get(key) {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('kv', 'readonly');
const r = tx.objectStore('kv').get(key);
r.onsuccess = () => res(r.result);
r.onerror = () => rej(r.error);
});
}
async function set(key, val) {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('kv', 'readwrite');
tx.objectStore('kv').put(val, key);
tx.oncomplete = () => res();
tx.onerror = () => rej(tx.error);
});
}
async function del(key) {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('kv', 'readwrite');
tx.objectStore('kv').delete(key);
tx.oncomplete = () => res();
tx.onerror = () => rej(tx.error);
});
}
async function queuePush(item) {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('queue', 'readwrite');
const r = tx.objectStore('queue').add(item);
r.onsuccess = () => res(r.result);
r.onerror = () => rej(r.error);
});
}
async function queueAll() {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('queue', 'readonly');
const r = tx.objectStore('queue').getAll();
r.onsuccess = () => res(r.result || []);
r.onerror = () => rej(r.error);
});
}
async function queueDelete(id) {
const db = await open();
return new Promise((res, rej) => {
const tx = db.transaction('queue', 'readwrite');
tx.objectStore('queue').delete(id);
tx.oncomplete = () => res();
tx.onerror = () => rej(tx.error);
});
}
window.idb = { get, set, del, queuePush, queueAll, queueDelete };
})();