662 lines
24 KiB
JavaScript
662 lines
24 KiB
JavaScript
// Admin JavaScript
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// Benutzer-Formular
|
||
const form = document.getElementById('addUserForm');
|
||
|
||
form.addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
// Rollen aus Checkboxen sammeln
|
||
const roleCheckboxes = document.querySelectorAll('input[name="roles"]:checked');
|
||
const roles = Array.from(roleCheckboxes).map(cb => cb.value);
|
||
|
||
// Validierung: Mindestens eine Rolle muss ausgewählt sein
|
||
if (roles.length === 0) {
|
||
alert('Bitte wählen Sie mindestens eine Rolle aus.');
|
||
return;
|
||
}
|
||
|
||
const defaultBreakInput = document.getElementById('defaultBreakMinutes');
|
||
const defaultBreakVal = defaultBreakInput && defaultBreakInput.value !== '' ? parseInt(defaultBreakInput.value, 10) : 30;
|
||
const default_break_minutes = (!isNaN(defaultBreakVal) && defaultBreakVal >= 0) ? defaultBreakVal : 30;
|
||
|
||
const formData = {
|
||
username: document.getElementById('username').value,
|
||
password: document.getElementById('password').value,
|
||
firstname: document.getElementById('firstname').value,
|
||
lastname: document.getElementById('lastname').value,
|
||
roles: roles,
|
||
personalnummer: document.getElementById('personalnummer').value,
|
||
wochenstunden: document.getElementById('wochenstunden').value,
|
||
arbeitstage: document.getElementById('arbeitstage').value,
|
||
urlaubstage: document.getElementById('urlaubstage').value,
|
||
default_break_minutes: default_break_minutes
|
||
};
|
||
|
||
try {
|
||
const response = await fetch('/admin/users', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(formData)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
alert('Benutzer wurde erfolgreich angelegt!');
|
||
location.reload();
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'Benutzer konnte nicht angelegt werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Anlegen des Benutzers');
|
||
}
|
||
});
|
||
|
||
// LDAP-Konfiguration laden
|
||
loadLDAPConfig();
|
||
|
||
// Optionen laden
|
||
loadOptions();
|
||
|
||
// MSSQL-Konfiguration laden
|
||
loadMssqlConfig();
|
||
|
||
// Timesheet-Duplikate Button
|
||
const loadTimesheetDuplicatesBtn = document.getElementById('loadTimesheetDuplicatesBtn');
|
||
if (loadTimesheetDuplicatesBtn) {
|
||
loadTimesheetDuplicatesBtn.addEventListener('click', function() {
|
||
loadTimesheetDuplicates();
|
||
});
|
||
}
|
||
|
||
// Optionen-Formular
|
||
const optionsForm = document.getElementById('optionsForm');
|
||
if (optionsForm) {
|
||
optionsForm.addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = {
|
||
saturday_percentage: document.getElementById('saturdayPercentage').value,
|
||
sunday_percentage: document.getElementById('sundayPercentage').value,
|
||
checkin_root_url: document.getElementById('checkinRootUrl') ? document.getElementById('checkinRootUrl').value : null
|
||
};
|
||
|
||
try {
|
||
const response = await fetch('/admin/options', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(formData)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
alert('Optionen wurden erfolgreich gespeichert!');
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'Optionen konnten nicht gespeichert werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Speichern der Optionen');
|
||
}
|
||
});
|
||
}
|
||
|
||
// LDAP-Konfigurationsformular
|
||
const ldapConfigForm = document.getElementById('ldapConfigForm');
|
||
if (ldapConfigForm) {
|
||
ldapConfigForm.addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
const enabled = document.getElementById('ldapEnabled').checked;
|
||
const url = document.getElementById('ldapUrl').value;
|
||
const baseDn = document.getElementById('ldapBaseDn').value;
|
||
|
||
// Validierung: URL und Base DN sind erforderlich wenn aktiviert
|
||
if (enabled && (!url || !baseDn)) {
|
||
alert('Bitte füllen Sie URL und Base DN aus, wenn LDAP aktiviert ist.');
|
||
return;
|
||
}
|
||
|
||
const formData = {
|
||
enabled: enabled,
|
||
url: url,
|
||
bind_dn: document.getElementById('ldapBindDn').value,
|
||
bind_password: document.getElementById('ldapBindPassword').value,
|
||
base_dn: baseDn,
|
||
user_search_filter: document.getElementById('ldapSearchFilter').value,
|
||
username_attribute: document.getElementById('ldapUsernameAttr').value,
|
||
firstname_attribute: document.getElementById('ldapFirstnameAttr').value,
|
||
lastname_attribute: document.getElementById('ldapLastnameAttr').value,
|
||
sync_interval: parseInt(document.getElementById('ldapSyncInterval').value) || 0
|
||
};
|
||
|
||
try {
|
||
const response = await fetch('/admin/ldap/config', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(formData)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
alert('LDAP-Konfiguration wurde erfolgreich gespeichert!');
|
||
location.reload();
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'Konfiguration konnte nicht gespeichert werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Speichern der Konfiguration');
|
||
}
|
||
});
|
||
}
|
||
|
||
// MSSQL-Konfigurationsformular
|
||
const mssqlConfigForm = document.getElementById('mssqlConfigForm');
|
||
if (mssqlConfigForm) {
|
||
mssqlConfigForm.addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
const server = document.getElementById('mssqlServer').value;
|
||
const database = document.getElementById('mssqlDatabase').value;
|
||
const username = document.getElementById('mssqlUsername').value;
|
||
const password = document.getElementById('mssqlPassword').value;
|
||
|
||
if (!server || !database || !username) {
|
||
alert('Bitte Server, Datenbankname und Benutzername ausfüllen.');
|
||
return;
|
||
}
|
||
|
||
const formData = { server, database, username, password };
|
||
|
||
try {
|
||
const response = await fetch('/admin/mssql-config', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(formData)
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
alert('MSSQL-Konfiguration wurde erfolgreich gespeichert!');
|
||
// Passwort-Feld leeren nach dem Speichern
|
||
document.getElementById('mssqlPassword').value = '';
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'MSSQL-Konfiguration konnte nicht gespeichert werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Speichern der MSSQL-Konfiguration');
|
||
}
|
||
});
|
||
}
|
||
|
||
// MSSQL Test-Verbindung
|
||
const mssqlTestBtn = document.getElementById('mssqlTestConnectionBtn');
|
||
if (mssqlTestBtn) {
|
||
mssqlTestBtn.addEventListener('click', async function() {
|
||
const statusEl = document.getElementById('mssqlTestStatus');
|
||
mssqlTestBtn.disabled = true;
|
||
if (statusEl) {
|
||
statusEl.textContent = 'Verbindung wird getestet...';
|
||
statusEl.style.color = 'blue';
|
||
}
|
||
|
||
try {
|
||
const response = await fetch('/admin/mssql-test-connection', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result && result.success) {
|
||
if (statusEl) {
|
||
statusEl.textContent = 'Verbindung erfolgreich.';
|
||
statusEl.style.color = 'green';
|
||
}
|
||
} else {
|
||
const msg = (result && result.error) ? result.error : 'Testverbindung fehlgeschlagen.';
|
||
if (statusEl) {
|
||
statusEl.textContent = msg;
|
||
statusEl.style.color = 'red';
|
||
}
|
||
alert(msg);
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler bei MSSQL-Testverbindung:', error);
|
||
if (statusEl) {
|
||
statusEl.textContent = 'Fehler bei der Testverbindung.';
|
||
statusEl.style.color = 'red';
|
||
}
|
||
alert('Fehler bei der Testverbindung zur MSSQL-Datenbank.');
|
||
} finally {
|
||
mssqlTestBtn.disabled = false;
|
||
}
|
||
});
|
||
}
|
||
|
||
// Sync-Button
|
||
const syncNowBtn = document.getElementById('syncNowBtn');
|
||
if (syncNowBtn) {
|
||
syncNowBtn.addEventListener('click', async function() {
|
||
if (!confirm('Möchten Sie die LDAP-Synchronisation jetzt starten?')) {
|
||
return;
|
||
}
|
||
|
||
const statusEl = document.getElementById('syncStatus');
|
||
syncNowBtn.disabled = true;
|
||
statusEl.textContent = 'Synchronisation läuft...';
|
||
statusEl.style.color = 'blue';
|
||
|
||
try {
|
||
const response = await fetch('/admin/ldap/sync', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
statusEl.textContent = `Erfolgreich: ${result.synced} Benutzer synchronisiert`;
|
||
statusEl.style.color = 'green';
|
||
|
||
if (result.errors && result.errors.length > 0) {
|
||
alert('Synchronisation abgeschlossen mit Warnungen:\n' + result.errors.join('\n'));
|
||
} else {
|
||
alert(`Synchronisation erfolgreich abgeschlossen: ${result.synced} Benutzer synchronisiert`);
|
||
}
|
||
|
||
// Seite neu laden nach kurzer Verzögerung
|
||
setTimeout(() => {
|
||
location.reload();
|
||
}, 2000);
|
||
} else {
|
||
statusEl.textContent = 'Fehler: ' + (result.error || 'Synchronisation fehlgeschlagen');
|
||
statusEl.style.color = 'red';
|
||
alert('Fehler: ' + (result.error || 'Synchronisation fehlgeschlagen'));
|
||
syncNowBtn.disabled = false;
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
statusEl.textContent = 'Fehler bei der Synchronisation';
|
||
statusEl.style.color = 'red';
|
||
alert('Fehler bei der Synchronisation');
|
||
syncNowBtn.disabled = false;
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
async function loadTimesheetDuplicates() {
|
||
const container = document.getElementById('timesheetDuplicatesContainer');
|
||
if (!container) return;
|
||
|
||
container.innerHTML = '<p style="color: #666;">Lade Timesheet-Duplikate...</p>';
|
||
|
||
try {
|
||
const response = await fetch('/admin/api/timesheet-duplicates');
|
||
const result = await response.json();
|
||
|
||
if (!response.ok) {
|
||
const msg = result && result.error ? result.error : 'Fehler beim Laden der Timesheet-Duplikate.';
|
||
container.innerHTML = `<p style="color: red;">${msg}</p>`;
|
||
return;
|
||
}
|
||
|
||
const groups = Array.isArray(result.groups) ? result.groups : [];
|
||
|
||
if (groups.length === 0) {
|
||
container.innerHTML = '<p style="color: green;">Es wurden keine doppelten Timesheet-Einträge gefunden. Alles sauber.</p>';
|
||
return;
|
||
}
|
||
|
||
let html = '';
|
||
groups.forEach((group, index) => {
|
||
const headerLabel = `${group.user_name || group.username || ('User #' + group.user_id)} – ${group.date} (Anzahl Einträge: ${group.entry_count})`;
|
||
html += `
|
||
<div class="timesheet-duplicate-group" style="border: 1px solid #ddd; border-radius: 4px; margin-bottom: 15px;">
|
||
<div style="padding: 10px 15px; background-color: #f5f5f5; display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<strong>Gruppe ${index + 1}</strong>: ${headerLabel}
|
||
</div>
|
||
</div>
|
||
<div style="padding: 10px 15px; overflow-x: auto;">
|
||
<table style="width: 100%; min-width: 800px; border-collapse: collapse;">
|
||
<thead>
|
||
<tr>
|
||
<th style="text-align:left; padding:4px;">ID</th>
|
||
<th style="text-align:left; padding:4px;">Start</th>
|
||
<th style="text-align:left; padding:4px;">Ende</th>
|
||
<th style="text-align:left; padding:4px;">Pause (Min)</th>
|
||
<th style="text-align:left; padding:4px;">Stunden (total_hours)</th>
|
||
<th style="text-align:left; padding:4px;">Status</th>
|
||
<th style="text-align:left; padding:4px;">Erstellt</th>
|
||
<th style="text-align:left; padding:4px;">Aktualisiert</th>
|
||
<th style="text-align:left; padding:4px;">Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
`;
|
||
|
||
(group.entries || []).forEach(entry => {
|
||
const created = entry.created_at ? new Date(entry.created_at).toLocaleString('de-DE') : '-';
|
||
const updated = entry.updated_at ? new Date(entry.updated_at).toLocaleString('de-DE') : '-';
|
||
const totalHours = entry.total_hours != null ? entry.total_hours : '-';
|
||
const status = entry.status || '-';
|
||
const breakMinutes = entry.break_minutes != null ? entry.break_minutes : 0;
|
||
|
||
html += `
|
||
<tr>
|
||
<td style="padding:4px;">${entry.id}</td>
|
||
<td style="padding:4px;">${entry.start_time || '-'}</td>
|
||
<td style="padding:4px;">${entry.end_time || '-'}</td>
|
||
<td style="padding:4px;">${breakMinutes}</td>
|
||
<td style="padding:4px;">${totalHours}</td>
|
||
<td style="padding:4px;">${status}</td>
|
||
<td style="padding:4px;">${created}</td>
|
||
<td style="padding:4px;">${updated}</td>
|
||
<td style="padding:4px;">
|
||
<button type="button" class="btn btn-danger btn-sm" onclick="deleteTimesheetEntry(${entry.id})">
|
||
Eintrag löschen
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
`;
|
||
});
|
||
|
||
html += `
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
container.innerHTML = html;
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der Timesheet-Duplikate:', error);
|
||
container.innerHTML = '<p style="color: red;">Fehler beim Laden der Timesheet-Duplikate.</p>';
|
||
}
|
||
}
|
||
|
||
async function deleteTimesheetEntry(entryId) {
|
||
|
||
try {
|
||
const response = await fetch(`/admin/api/timesheet-entry/${entryId}`, {
|
||
method: 'DELETE',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result && result.success) {
|
||
// Liste neu laden, um den aktuellen Stand anzuzeigen
|
||
loadTimesheetDuplicates();
|
||
} else {
|
||
const msg = (result && result.error) ? result.error : 'Timesheet-Eintrag konnte nicht gelöscht werden.';
|
||
alert('Fehler: ' + msg);
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Löschen des Timesheet-Eintrags:', error);
|
||
alert('Fehler beim Löschen des Timesheet-Eintrags.');
|
||
}
|
||
}
|
||
|
||
// Optionen laden und Formular ausfüllen
|
||
async function loadOptions() {
|
||
try {
|
||
const response = await fetch('/admin/options');
|
||
const result = await response.json();
|
||
|
||
if (result.config) {
|
||
const config = result.config;
|
||
|
||
if (document.getElementById('saturdayPercentage')) {
|
||
document.getElementById('saturdayPercentage').value = config.saturday_percentage || 0;
|
||
}
|
||
if (document.getElementById('sundayPercentage')) {
|
||
document.getElementById('sundayPercentage').value = config.sunday_percentage || 0;
|
||
}
|
||
if (document.getElementById('checkinRootUrl')) {
|
||
document.getElementById('checkinRootUrl').value = config.checkin_root_url || '';
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der Optionen:', error);
|
||
}
|
||
}
|
||
|
||
// LDAP-Konfiguration laden und Formular ausfüllen
|
||
async function loadLDAPConfig() {
|
||
try {
|
||
const response = await fetch('/admin/ldap/config');
|
||
const result = await response.json();
|
||
|
||
if (result.config) {
|
||
const config = result.config;
|
||
|
||
if (document.getElementById('ldapEnabled')) {
|
||
document.getElementById('ldapEnabled').checked = config.enabled === 1;
|
||
}
|
||
if (document.getElementById('ldapUrl')) {
|
||
document.getElementById('ldapUrl').value = config.url || '';
|
||
}
|
||
if (document.getElementById('ldapBaseDn')) {
|
||
document.getElementById('ldapBaseDn').value = config.base_dn || '';
|
||
}
|
||
if (document.getElementById('ldapBindDn')) {
|
||
document.getElementById('ldapBindDn').value = config.bind_dn || '';
|
||
}
|
||
if (document.getElementById('ldapSearchFilter')) {
|
||
document.getElementById('ldapSearchFilter').value = config.user_search_filter || '(objectClass=person)';
|
||
}
|
||
if (document.getElementById('ldapUsernameAttr')) {
|
||
document.getElementById('ldapUsernameAttr').value = config.username_attribute || 'sAMAccountName';
|
||
}
|
||
if (document.getElementById('ldapFirstnameAttr')) {
|
||
document.getElementById('ldapFirstnameAttr').value = config.firstname_attribute || 'givenName';
|
||
}
|
||
if (document.getElementById('ldapLastnameAttr')) {
|
||
document.getElementById('ldapLastnameAttr').value = config.lastname_attribute || 'sn';
|
||
}
|
||
if (document.getElementById('ldapSyncInterval')) {
|
||
document.getElementById('ldapSyncInterval').value = config.sync_interval || 0;
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der LDAP-Konfiguration:', error);
|
||
}
|
||
}
|
||
|
||
// MSSQL-Konfiguration laden und Formular ausfüllen
|
||
async function loadMssqlConfig() {
|
||
try {
|
||
const response = await fetch('/admin/mssql-config');
|
||
const result = await response.json();
|
||
|
||
if (result.config) {
|
||
const config = result.config;
|
||
|
||
if (document.getElementById('mssqlServer')) {
|
||
document.getElementById('mssqlServer').value = config.server || '';
|
||
}
|
||
if (document.getElementById('mssqlDatabase')) {
|
||
document.getElementById('mssqlDatabase').value = config.database || '';
|
||
}
|
||
if (document.getElementById('mssqlUsername')) {
|
||
document.getElementById('mssqlUsername').value = config.username || '';
|
||
}
|
||
// Passwort wird aus Sicherheitsgründen nie vorausgefüllt
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der MSSQL-Konfiguration:', error);
|
||
}
|
||
}
|
||
|
||
async function deleteUser(userId, username) {
|
||
const confirmed = confirm(`Möchten Sie den Benutzer "${username}" wirklich löschen?`);
|
||
|
||
if (!confirmed) return;
|
||
|
||
try {
|
||
const response = await fetch(`/admin/users/${userId}`, {
|
||
method: 'DELETE'
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
alert('Benutzer wurde erfolgreich gelöscht!');
|
||
location.reload();
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'Benutzer konnte nicht gelöscht werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Löschen des Benutzers');
|
||
}
|
||
}
|
||
|
||
// User bearbeiten
|
||
function editUser(userId) {
|
||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||
if (!row) return;
|
||
|
||
// Alle Display-Felder ausblenden und Edit-Felder einblenden
|
||
row.querySelectorAll('.user-field-display').forEach(display => {
|
||
display.style.display = 'none';
|
||
});
|
||
row.querySelectorAll('.user-field-edit').forEach(edit => {
|
||
edit.style.display = 'inline-block';
|
||
});
|
||
|
||
// Buttons umschalten
|
||
row.querySelector('.edit-user-btn').style.display = 'none';
|
||
row.querySelector('.save-user-btn').style.display = 'inline-block';
|
||
row.querySelector('.cancel-user-btn').style.display = 'inline-block';
|
||
}
|
||
|
||
// User speichern
|
||
async function saveUser(userId) {
|
||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||
if (!row) return;
|
||
|
||
const personalnummer = row.querySelector('input[data-field="personalnummer"]').value;
|
||
const wochenstunden = row.querySelector('input[data-field="wochenstunden"]').value;
|
||
const arbeitstage = row.querySelector('input[data-field="arbeitstage"]').value;
|
||
const urlaubstage = row.querySelector('input[data-field="urlaubstage"]').value;
|
||
const defaultBreakInput = row.querySelector('input[data-field="default_break_minutes"]');
|
||
const default_break_minutes = defaultBreakInput && defaultBreakInput.value !== '' ? parseInt(defaultBreakInput.value, 10) : 30;
|
||
const normalizedDefaultBreak = (!isNaN(default_break_minutes) && default_break_minutes >= 0) ? default_break_minutes : 30;
|
||
|
||
// Rollen aus Checkboxen sammeln
|
||
const roleCheckboxes = row.querySelectorAll('.role-checkbox:checked');
|
||
const roles = Array.from(roleCheckboxes).map(cb => cb.value);
|
||
|
||
// Validierung: Mindestens eine Rolle erforderlich
|
||
if (roles.length === 0) {
|
||
alert('Mindestens eine Rolle muss ausgewählt sein.');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/admin/users/${userId}`, {
|
||
method: 'PUT',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({
|
||
personalnummer: personalnummer || null,
|
||
wochenstunden: wochenstunden || null,
|
||
arbeitstage: arbeitstage || 5,
|
||
urlaubstage: urlaubstage || null,
|
||
default_break_minutes: normalizedDefaultBreak,
|
||
roles: roles
|
||
})
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
// Werte in Display-Felder übernehmen
|
||
row.querySelector('span[data-field="personalnummer"]').textContent = personalnummer || '-';
|
||
row.querySelector('span[data-field="wochenstunden"]').textContent = wochenstunden || '-';
|
||
row.querySelector('span[data-field="urlaubstage"]').textContent = urlaubstage || '-';
|
||
const defaultBreakDisplay = row.querySelector('span[data-field="default_break_minutes"]');
|
||
if (defaultBreakDisplay) defaultBreakDisplay.textContent = normalizedDefaultBreak;
|
||
|
||
// Rollen-Display aktualisieren
|
||
const rolesDisplay = row.querySelector('div[data-field="roles"]');
|
||
if (rolesDisplay) {
|
||
const roleLabels = { 'mitarbeiter': 'Mitarbeiter', 'verwaltung': 'Verwaltung', 'admin': 'Admin' };
|
||
rolesDisplay.innerHTML = roles.map(role =>
|
||
`<span class="role-badge role-${role}" style="margin-right: 5px;">${roleLabels[role] || role}</span>`
|
||
).join('');
|
||
}
|
||
|
||
// Bearbeitung beenden
|
||
cancelEditUser(userId);
|
||
alert('Benutzerdaten wurden erfolgreich gespeichert!');
|
||
// Seite neu laden um sicherzustellen dass alles korrekt ist
|
||
location.reload();
|
||
} else {
|
||
alert('Fehler: ' + (result.error || 'Daten konnten nicht gespeichert werden'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler:', error);
|
||
alert('Fehler beim Speichern der Benutzerdaten');
|
||
}
|
||
}
|
||
|
||
// Bearbeitung abbrechen
|
||
function cancelEditUser(userId) {
|
||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||
if (!row) return;
|
||
|
||
// Alle Edit-Felder ausblenden und Display-Felder einblenden
|
||
row.querySelectorAll('.user-field-edit').forEach(edit => {
|
||
edit.style.display = 'none';
|
||
// Wert zurücksetzen (nur für Input-Felder, nicht für Rollen)
|
||
const field = edit.dataset.field;
|
||
if (field !== 'roles') {
|
||
const display = row.querySelector(`span[data-field="${field}"]`);
|
||
if (display && edit.tagName === 'INPUT') {
|
||
edit.value = display.textContent === '-' ? '' : display.textContent;
|
||
}
|
||
}
|
||
});
|
||
row.querySelectorAll('.user-field-display').forEach(display => {
|
||
if (display.tagName === 'DIV' || display.tagName === 'SPAN') {
|
||
display.style.display = 'block';
|
||
} else {
|
||
display.style.display = 'inline';
|
||
}
|
||
});
|
||
|
||
// Buttons umschalten
|
||
row.querySelector('.edit-user-btn').style.display = 'inline-block';
|
||
row.querySelector('.save-user-btn').style.display = 'none';
|
||
row.querySelector('.cancel-user-btn').style.display = 'none';
|
||
}
|