feat(sync): Frontend pusht Aenderungen und laedt Server-Stand beim Start

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenearos 2026-07-07 15:59:48 +02:00
parent 787bc1416b
commit 67a3f4b546
4 changed files with 23 additions and 2 deletions

6
app.js
View file

@ -1230,7 +1230,11 @@ class DienstplanApp {
// Initialize app when DOM is ready // Initialize app when DOM is ready
let app; let app;
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', async () => {
if (window.DataSync) {
try { await window.DataSync.boot(); }
catch (e) { console.error('Sync-Boot fehlgeschlagen, App laeuft lokal weiter:', e); }
}
app = new DienstplanApp(); app = new DienstplanApp();
window.app = app; window.app = app;
}); });

View file

@ -326,6 +326,7 @@
<script src="variants.js"></script> <script src="variants.js"></script>
<script src="calculator.js"></script> <script src="calculator.js"></script>
<script src="storage.js"></script> <script src="storage.js"></script>
<script src="sync.js"></script>
<script src="app.js"></script> <script src="app.js"></script>
<script src="image-import.js"></script> <script src="image-import.js"></script>
</body> </body>

View file

@ -45,6 +45,7 @@ class DataStorage {
throw new TypeError('employees muss ein Array sein'); throw new TypeError('employees muss ein Array sein');
} }
localStorage.setItem(this.STORAGE_KEY_EMPLOYEES, JSON.stringify(employees)); localStorage.setItem(this.STORAGE_KEY_EMPLOYEES, JSON.stringify(employees));
this._notifyChange();
} catch (e) { } catch (e) {
console.error('Fehler beim Speichern der Mitarbeiter-Daten:', e); console.error('Fehler beim Speichern der Mitarbeiter-Daten:', e);
throw e; throw e;
@ -117,6 +118,7 @@ class DataStorage {
throw new TypeError('duties muss ein gültiges Objekt sein'); throw new TypeError('duties muss ein gültiges Objekt sein');
} }
localStorage.setItem(this.STORAGE_KEY_DUTIES, JSON.stringify(duties)); localStorage.setItem(this.STORAGE_KEY_DUTIES, JSON.stringify(duties));
this._notifyChange();
} catch (e) { } catch (e) {
console.error('Fehler beim Speichern der Dienst-Daten:', e); console.error('Fehler beim Speichern der Dienst-Daten:', e);
throw e; throw e;
@ -285,6 +287,7 @@ class DataStorage {
if (!map[employeeName]) map[employeeName] = {}; if (!map[employeeName]) map[employeeName] = {};
map[employeeName][yearMonth] = Boolean(value); map[employeeName][yearMonth] = Boolean(value);
localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(map)); localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(map));
this._notifyChange();
} catch (e) { } catch (e) {
console.error('Fehler beim Speichern des Urlaubsmodus:', e); console.error('Fehler beim Speichern des Urlaubsmodus:', e);
throw e; throw e;
@ -319,6 +322,16 @@ class DataStorage {
return map; return map;
} }
/**
* Signalisiert dem Sync-Layer eine Aenderung (falls vorhanden).
* Wird unterdrueckt, waehrend DataSync gerade Server-Daten uebernimmt.
*/
_notifyChange() {
if (typeof window !== 'undefined' && window.DataSync && !window.DataSync._applying) {
window.DataSync.push();
}
}
/** /**
* Clear all data * Clear all data
*/ */
@ -326,6 +339,7 @@ class DataStorage {
localStorage.removeItem(this.STORAGE_KEY_EMPLOYEES); localStorage.removeItem(this.STORAGE_KEY_EMPLOYEES);
localStorage.removeItem(this.STORAGE_KEY_DUTIES); localStorage.removeItem(this.STORAGE_KEY_DUTIES);
localStorage.removeItem(this.STORAGE_KEY_VACATION); localStorage.removeItem(this.STORAGE_KEY_VACATION);
this._notifyChange();
} }
/** /**
@ -363,6 +377,7 @@ class DataStorage {
if (data.vacation && typeof data.vacation === 'object') { if (data.vacation && typeof data.vacation === 'object') {
localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(data.vacation)); localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(data.vacation));
} }
this._notifyChange();
return true; return true;
} catch (e) { } catch (e) {
console.error('Import failed:', e); console.error('Import failed:', e);

3
sw.js
View file

@ -1,4 +1,4 @@
const CACHE_NAME = 'dienstplan-pro-v4'; const CACHE_NAME = 'dienstplan-pro-v5';
const ASSETS = [ const ASSETS = [
'./', './',
'./index.html', './index.html',
@ -8,6 +8,7 @@ const ASSETS = [
'./variants.js', './variants.js',
'./holidays.js', './holidays.js',
'./storage.js', './storage.js',
'./sync.js',
'./image-import.js' './image-import.js'
]; ];