feat: add dienstplan_vacation key + getVacationMode/setVacationMode + export/import
This commit is contained in:
parent
b921592f7e
commit
68f35d3e3d
2 changed files with 130 additions and 4 deletions
61
storage.js
61
storage.js
|
|
@ -6,6 +6,7 @@ class DataStorage {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.STORAGE_KEY_EMPLOYEES = 'dienstplan_employees';
|
this.STORAGE_KEY_EMPLOYEES = 'dienstplan_employees';
|
||||||
this.STORAGE_KEY_DUTIES = 'dienstplan_duties';
|
this.STORAGE_KEY_DUTIES = 'dienstplan_duties';
|
||||||
|
this.STORAGE_KEY_VACATION = 'dienstplan_vacation';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -260,12 +261,64 @@ class DataStorage {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get vacation mode for an employee in a specific month.
|
||||||
|
* @param {string} employeeName
|
||||||
|
* @param {string} yearMonth - format "YYYY-MM"
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getVacationMode(employeeName, yearMonth) {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(this.STORAGE_KEY_VACATION);
|
||||||
|
if (!raw) return false;
|
||||||
|
const map = JSON.parse(raw);
|
||||||
|
if (!map || typeof map !== 'object') return false;
|
||||||
|
return Boolean(map[employeeName] && map[employeeName][yearMonth]);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fehler beim Laden des Urlaubsmodus:', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set vacation mode for an employee in a specific month.
|
||||||
|
*/
|
||||||
|
setVacationMode(employeeName, yearMonth, value) {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(this.STORAGE_KEY_VACATION);
|
||||||
|
const map = raw ? JSON.parse(raw) : {};
|
||||||
|
if (!map[employeeName]) map[employeeName] = {};
|
||||||
|
map[employeeName][yearMonth] = Boolean(value);
|
||||||
|
localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(map));
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fehler beim Speichern des Urlaubsmodus:', e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the full vacation map ({ name: { yearMonth: bool } }).
|
||||||
|
*/
|
||||||
|
getAllVacationModes() {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(this.STORAGE_KEY_VACATION);
|
||||||
|
if (!raw) return {};
|
||||||
|
const map = JSON.parse(raw);
|
||||||
|
if (!map || typeof map !== 'object') return {};
|
||||||
|
return map;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fehler beim Laden des Urlaubsmodus:', e);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all data
|
* Clear all data
|
||||||
*/
|
*/
|
||||||
clearAll() {
|
clearAll() {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -276,7 +329,8 @@ class DataStorage {
|
||||||
try {
|
try {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
employees: this.getEmployees(),
|
employees: this.getEmployees(),
|
||||||
duties: this.getAllDuties()
|
duties: this.getAllDuties(),
|
||||||
|
vacation: this.getAllVacationModes()
|
||||||
}, null, 2);
|
}, null, 2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Fehler beim Exportieren der Daten:', e);
|
console.error('Fehler beim Exportieren der Daten:', e);
|
||||||
|
|
@ -296,11 +350,12 @@ class DataStorage {
|
||||||
if (data.employees) {
|
if (data.employees) {
|
||||||
this.saveEmployees(data.employees);
|
this.saveEmployees(data.employees);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.duties) {
|
if (data.duties) {
|
||||||
this.saveAllDuties(data.duties);
|
this.saveAllDuties(data.duties);
|
||||||
}
|
}
|
||||||
|
if (data.vacation && typeof data.vacation === 'object') {
|
||||||
|
localStorage.setItem(this.STORAGE_KEY_VACATION, JSON.stringify(data.vacation));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Import failed:', e);
|
console.error('Import failed:', e);
|
||||||
|
|
|
||||||
|
|
@ -393,6 +393,77 @@ runner.test('Storage: Export und Import', (t) => {
|
||||||
t.assertEqual(duties.length, 1, 'Sollte 1 Dienst haben');
|
t.assertEqual(duties.length, 1, 'Sollte 1 Dienst haben');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Storage - Vacation Mode
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
runner.test('Storage: getVacationMode fuer unbekannten MA -> false', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.clearAll();
|
||||||
|
t.assertFalse(storage.getVacationMode('Niemand', '2025-11'), 'leerer Default false');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: setVacationMode -> getVacationMode round-trip', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.clearAll();
|
||||||
|
storage.setVacationMode('Max Mustermann', '2025-11', true);
|
||||||
|
t.assertTrue(storage.getVacationMode('Max Mustermann', '2025-11'), 'true round-trip');
|
||||||
|
t.assertFalse(storage.getVacationMode('Max Mustermann', '2025-12'), 'anderer Monat = false');
|
||||||
|
t.assertFalse(storage.getVacationMode('Anna Schmidt', '2025-11'), 'anderer MA = false');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: setVacationMode kann zurueckgesetzt werden', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.clearAll();
|
||||||
|
storage.setVacationMode('Max Mustermann', '2025-11', true);
|
||||||
|
storage.setVacationMode('Max Mustermann', '2025-11', false);
|
||||||
|
t.assertFalse(storage.getVacationMode('Max Mustermann', '2025-11'), 'wieder false');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: Export enthaelt dienstplan_vacation', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.clearAll();
|
||||||
|
storage.addEmployee('Max Mustermann');
|
||||||
|
storage.setVacationMode('Max Mustermann', '2025-11', true);
|
||||||
|
const exported = storage.exportData();
|
||||||
|
const parsed = JSON.parse(exported);
|
||||||
|
t.assertTrue('vacation' in parsed, 'vacation key im Export');
|
||||||
|
t.assertEqual(parsed.vacation['Max Mustermann']['2025-11'], true, 'Wert exportiert');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: Import restauriert vacation', (t) => {
|
||||||
|
const storage1 = new DataStorage();
|
||||||
|
storage1.clearAll();
|
||||||
|
storage1.addEmployee('Max Mustermann');
|
||||||
|
storage1.setVacationMode('Max Mustermann', '2025-11', true);
|
||||||
|
const exported = storage1.exportData();
|
||||||
|
|
||||||
|
const storage2 = new DataStorage();
|
||||||
|
storage2.clearAll();
|
||||||
|
const ok = storage2.importData(exported);
|
||||||
|
t.assertTrue(ok, 'Import success');
|
||||||
|
t.assertTrue(storage2.getVacationMode('Max Mustermann', '2025-11'), 'vacation restauriert');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: Import ohne vacation-Feld bleibt fehlerfrei', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.clearAll();
|
||||||
|
const legacyJson = JSON.stringify({
|
||||||
|
employees: ['Max Mustermann'],
|
||||||
|
duties: {}
|
||||||
|
});
|
||||||
|
const ok = storage.importData(legacyJson);
|
||||||
|
t.assertTrue(ok, 'Legacy import erfolgreich');
|
||||||
|
t.assertFalse(storage.getVacationMode('Max Mustermann', '2025-11'), 'Default false');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.test('Storage: clearAll entfernt auch vacation', (t) => {
|
||||||
|
const storage = new DataStorage();
|
||||||
|
storage.setVacationMode('Max Mustermann', '2025-11', true);
|
||||||
|
storage.clearAll();
|
||||||
|
t.assertFalse(storage.getVacationMode('Max Mustermann', '2025-11'), 'nach clearAll false');
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Edge Cases & Regression Tests
|
// Edge Cases & Regression Tests
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue