Files
SDSStundenerfassung/views/admin.ejs
2026-03-18 17:24:13 +01:00

644 lines
32 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin - Stundenerfassung</title>
<link rel="icon" type="image/png" href="/images/favicon.png">
<link rel="stylesheet" href="/css/style.css">
<%- include('header') %>
</head>
<body>
<div class="navbar">
<div class="container">
<div class="navbar-brand">
<img src="/images/header.png" alt="Logo" class="navbar-logo">
<h1>Stundenerfassung - Admin</h1>
</div>
<div class="nav-right">
<span>Admin: <%= user.firstname %> <%= user.lastname %></span>
<% if (user.roles && user.roles.length > 1) { %>
<select id="roleSwitcher" class="role-switcher" style="margin-right: 10px; padding: 5px 10px; border-radius: 4px; border: 1px solid #ddd;">
<% const roleLabels = { 'mitarbeiter': 'Mitarbeiter', 'verwaltung': 'Verwaltung', 'admin': 'Administrator' }; %>
<% user.roles.forEach(function(role) { %>
<option value="<%= role %>" <%= user.currentRole === role ? 'selected' : '' %>><%= roleLabels[role] || role %></option>
<% }); %>
</select>
<% } %>
<a href="/logout" class="btn btn-logout">Abmelden</a>
</div>
</div>
</div>
<div class="admin-container">
<div class="container">
<div class="admin-panel">
<h2>Benutzerverwaltung</h2>
<!-- Benutzer anlegen - Zusammenklappbar -->
<div class="add-user-section" style="margin-top: 20px;">
<div class="collapsible-header" onclick="toggleAddUserSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0;">Neuen Benutzer anlegen</h3>
<span id="addUserToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="addUserContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<div class="add-user-form">
<form id="addUserForm">
<div class="form-row">
<div class="form-group">
<label for="firstname">Vorname</label>
<input type="text" id="firstname" name="firstname" required>
</div>
<div class="form-group">
<label for="lastname">Nachname</label>
<input type="text" id="lastname" name="lastname" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="username">Benutzername</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Passwort</label>
<input type="password" id="password" name="password" required>
</div>
</div>
<div class="form-group">
<label>Rollen</label>
<div class="roles-checkbox-group">
<label class="role-checkbox-label">
<input type="checkbox" name="roles" value="mitarbeiter" class="role-checkbox-input">
<span class="role-checkbox-text">Mitarbeiter</span>
</label>
<label class="role-checkbox-label">
<input type="checkbox" name="roles" value="verwaltung" class="role-checkbox-input">
<span class="role-checkbox-text">Verwaltung</span>
</label>
<label class="role-checkbox-label">
<input type="checkbox" name="roles" value="admin" class="role-checkbox-input">
<span class="role-checkbox-text">Administrator</span>
</label>
</div>
<small class="form-help-text">Wählen Sie eine oder mehrere Rollen aus</small>
</div>
<div class="form-row">
<div class="form-group">
<label for="personalnummer">Personalnummer</label>
<input type="text" id="personalnummer" name="personalnummer">
</div>
<div class="form-group">
<label for="wochenstunden">Wochenstunden</label>
<input type="number" id="wochenstunden" name="wochenstunden" step="0.5" min="0" placeholder="z.B. 40">
</div>
<div class="form-group">
<label for="arbeitstage">Arbeitstage pro Woche</label>
<input type="number" id="arbeitstage" name="arbeitstage" step="1" min="1" max="7" value="5" placeholder="z.B. 5">
</div>
<div class="form-group">
<label for="urlaubstage">Urlaubstage</label>
<input type="number" id="urlaubstage" name="urlaubstage" step="0.5" min="0" placeholder="z.B. 25">
</div>
<div class="form-group">
<label for="defaultBreakMinutes">Standard-Pausenzeit (Min)</label>
<input type="number" id="defaultBreakMinutes" name="default_break_minutes" min="0" step="15" placeholder="30">
<small style="color: #666; display: block; margin-top: 5px;">Vorbelegung Pausenzeit pro Tag (Min., mind. 0).</small>
</div>
</div>
<button type="submit" class="btn btn-primary">Benutzer anlegen</button>
</form>
</div>
</div>
</div>
<!-- Benutzer-Liste - Zusammenklappbar -->
<div class="user-list-section" style="margin-top: 20px;">
<div class="collapsible-header" onclick="toggleUserListSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0;">Benutzer-Liste</h3>
<span id="userListToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="userListContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff; overflow-x: auto; max-width: 100%;">
<div class="user-list" style="min-width: 100%;">
<table style="width: 100%; min-width: 900px;">
<thead>
<tr>
<th>ID</th>
<th>Benutzername</th>
<th>Vorname</th>
<th>Nachname</th>
<th>Rolle</th>
<th>Personalnummer</th>
<th>Wochenstunden</th>
<th>Arbeitstage pro Woche</th>
<th>Urlaubstage</th>
<th>Standard-Pause (Min)</th>
<th>Erstellt am</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<% users.forEach(function(u) { %>
<tr data-user-id="<%= u.id %>">
<td><%= u.id %></td>
<td><%= u.username %></td>
<td><%= u.firstname %></td>
<td><%= u.lastname %></td>
<td>
<div class="user-field-display" data-field="roles">
<%
const roleLabels = { 'mitarbeiter': 'Mitarbeiter', 'verwaltung': 'Verwaltung', 'admin': 'Admin' };
const userRoles = u.roles || [];
if (userRoles.length > 0) {
userRoles.forEach(function(role, idx) { %>
<span class="role-badge role-<%= role %>" style="margin-right: 5px;"><%= roleLabels[role] || role %></span>
<% });
} else {
%>
<span class="role-badge role-mitarbeiter">Mitarbeiter</span>
<% } %>
</div>
<div class="user-field-edit" data-field="roles" data-user-id="<%= u.id %>" style="display: none;">
<div class="roles-checkbox-group roles-checkbox-group-inline">
<label class="role-checkbox-label role-checkbox-label-small">
<input type="checkbox" class="role-checkbox role-checkbox-input" data-role="mitarbeiter" value="mitarbeiter" <%= userRoles.includes('mitarbeiter') ? 'checked' : '' %>>
<span class="role-checkbox-text">Mitarbeiter</span>
</label>
<label class="role-checkbox-label role-checkbox-label-small">
<input type="checkbox" class="role-checkbox role-checkbox-input" data-role="verwaltung" value="verwaltung" <%= userRoles.includes('verwaltung') ? 'checked' : '' %>>
<span class="role-checkbox-text">Verwaltung</span>
</label>
<label class="role-checkbox-label role-checkbox-label-small">
<input type="checkbox" class="role-checkbox role-checkbox-input" data-role="admin" value="admin" <%= userRoles.includes('admin') ? 'checked' : '' %>>
<span class="role-checkbox-text">Admin</span>
</label>
</div>
</div>
</td>
<td>
<span class="user-field-display" data-field="personalnummer"><%= u.personalnummer || '-' %></span>
<input type="text" class="user-field-edit" data-field="personalnummer" data-user-id="<%= u.id %>" value="<%= u.personalnummer || '' %>" style="display: none; width: 100px;">
</td>
<td>
<span class="user-field-display" data-field="wochenstunden"><%= u.wochenstunden || '-' %></span>
<input type="number" step="0.5" class="user-field-edit" data-field="wochenstunden" data-user-id="<%= u.id %>" value="<%= u.wochenstunden || '' %>" style="display: none; width: 80px;">
</td>
<td>
<span class="user-field-display" data-field="arbeitstage"><%= u.arbeitstage || 5 %></span>
<input type="number" step="1" min="1" max="7" class="user-field-edit" data-field="arbeitstage" data-user-id="<%= u.id %>" value="<%= u.arbeitstage || 5 %>" style="display: none; width: 80px;">
</td>
<td>
<span class="user-field-display" data-field="urlaubstage"><%= u.urlaubstage || '-' %></span>
<input type="number" step="0.5" class="user-field-edit" data-field="urlaubstage" data-user-id="<%= u.id %>" value="<%= u.urlaubstage || '' %>" style="display: none; width: 80px;">
</td>
<td>
<span class="user-field-display" data-field="default_break_minutes"><%= (u.default_break_minutes != null && u.default_break_minutes !== '') ? u.default_break_minutes : '-' %></span>
<input type="number" min="0" step="15" class="user-field-edit" data-field="default_break_minutes" data-user-id="<%= u.id %>" value="<%= (u.default_break_minutes != null && u.default_break_minutes !== '') ? u.default_break_minutes : '' %>" style="display: none; width: 80px;">
</td>
<td><%= new Date(u.created_at).toLocaleDateString('de-DE') %></td>
<td>
<button onclick="editUser(<%= u.id %>)" class="btn btn-primary btn-sm edit-user-btn" data-user-id="<%= u.id %>">Bearbeiten</button>
<button onclick="saveUser(<%= u.id %>)" class="btn btn-success btn-sm save-user-btn" data-user-id="<%= u.id %>" style="display: none;">Speichern</button>
<button onclick="cancelEditUser(<%= u.id %>)" class="btn btn-secondary btn-sm cancel-user-btn" data-user-id="<%= u.id %>" style="display: none;">Abbrechen</button>
<% if (u.id > 2) { %>
<button onclick="deleteUser(<%= u.id %>, '<%= u.username %>')" class="btn btn-danger btn-sm">Löschen</button>
<% } else { %>
<span class="text-muted">System</span>
<% } %>
</td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
</div>
<div class="options-section" style="margin-top: 40px;">
<div class="collapsible-header" onclick="toggleOptionsSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin: 0;">Optionen</h2>
<span id="optionsToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="optionsContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<div class="options-form">
<h3>Wochenend-Prozentsätze</h3>
<p style="margin-bottom: 20px; color: #666;">Konfigurieren Sie die Prozentsätze für die Wochenendstunden. 100% entspricht normal, 150% entspricht 1,5 mal, 200% entspricht doppelt.</p>
<form id="optionsForm">
<div class="form-row">
<div class="form-group">
<label for="saturdayPercentage">Samstag-Prozentsatz</label>
<select id="saturdayPercentage" name="saturday_percentage" class="form-control" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
<% for (let i = 100; i <= 200; i += 5) { %>
<option value="<%= i %>" <%= (typeof options !== 'undefined' && options && options.saturday_percentage == i) ? 'selected' : '' %>><%= i %>%</option>
<% } %>
</select>
</div>
<div class="form-group">
<label for="sundayPercentage">Sonntag-Prozentsatz</label>
<select id="sundayPercentage" name="sunday_percentage" class="form-control" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
<% for (let i = 100; i <= 200; i += 5) { %>
<option value="<%= i %>" <%= (typeof options !== 'undefined' && options && options.sunday_percentage == i) ? 'selected' : '' %>><%= i %>%</option>
<% } %>
</select>
</div>
</div>
<div class="form-group" style="margin-top: 20px;">
<h3 style="margin-bottom: 10px;">Check-in URL-Konfiguration</h3>
<p style="margin-bottom: 15px; color: #666;">Definieren Sie die Basis-URL für alle Check-in und Check-out URLs. Diese URL wird vor <code>/api</code> verwendet. Beispiel: https://example.com:3334</p>
<label for="checkinRootUrl">Check-in Root URL</label>
<input type="text" id="checkinRootUrl" name="checkin_root_url" class="form-control" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;" placeholder="https://example.com:3334" value="<%= (typeof options !== 'undefined' && options && options.checkin_root_url) ? options.checkin_root_url : '' %>">
<small style="color: #666; display: block; margin-top: 5px;">Lassen Sie dieses Feld leer, um die URL automatisch aus der aktuellen Seite zu generieren.</small>
</div>
<button type="submit" class="btn btn-primary">Optionen speichern</button>
</form>
</div>
</div>
</div>
<div class="ldap-sync-section" style="margin-top: 40px;">
<div class="collapsible-header" onclick="toggleLDAPSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin: 0;">LDAP-Synchronisation</h2>
<span id="ldapToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="ldapContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<div class="ldap-config-form">
<h3>LDAP-Konfiguration</h3>
<form id="ldapConfigForm">
<div class="form-group">
<label>
<input type="checkbox" id="ldapEnabled" name="enabled">
LDAP-Synchronisation aktivieren
</label>
</div>
<div class="form-row">
<div class="form-group">
<label for="ldapUrl">LDAP-Server URL</label>
<input type="text" id="ldapUrl" name="url" placeholder="ldap://ldap.example.com:389">
</div>
<div class="form-group">
<label for="ldapBaseDn">Base DN</label>
<input type="text" id="ldapBaseDn" name="base_dn" placeholder="dc=example,dc=com">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="ldapBindDn">Bind DN (optional)</label>
<input type="text" id="ldapBindDn" name="bind_dn" placeholder="cn=admin,dc=example,dc=com">
</div>
<div class="form-group">
<label for="ldapBindPassword">Bind Passwort (optional)</label>
<input type="password" id="ldapBindPassword" name="bind_password" placeholder="Leer lassen um nicht zu ändern">
</div>
</div>
<div class="form-group">
<label for="ldapSearchFilter">User Search Filter</label>
<input type="text" id="ldapSearchFilter" name="user_search_filter" placeholder="(objectClass=person)" value="(objectClass=person)">
</div>
<div class="form-row">
<div class="form-group">
<label for="ldapUsernameAttr">Username-Attribut</label>
<input type="text" id="ldapUsernameAttr" name="username_attribute" placeholder="sAMAccountName" value="sAMAccountName">
</div>
<div class="form-group">
<label for="ldapFirstnameAttr">Vorname-Attribut</label>
<input type="text" id="ldapFirstnameAttr" name="firstname_attribute" placeholder="givenName" value="givenName">
</div>
<div class="form-group">
<label for="ldapLastnameAttr">Nachname-Attribut</label>
<input type="text" id="ldapLastnameAttr" name="lastname_attribute" placeholder="sn" value="sn">
</div>
</div>
<div class="form-group">
<label for="ldapSyncInterval">Sync-Intervall (Minuten)</label>
<input type="number" id="ldapSyncInterval" name="sync_interval" min="0" value="0" placeholder="0 = nur manuell">
<small>0 = nur manuelle Synchronisation</small>
</div>
<button type="submit" class="btn btn-primary">Konfiguration speichern</button>
</form>
</div>
<div class="ldap-sync-actions" style="margin-top: 30px;">
<h3>Synchronisation</h3>
<div style="margin-bottom: 15px;">
<button id="syncNowBtn" class="btn btn-primary">Synchronisation jetzt starten</button>
<span id="syncStatus" style="margin-left: 15px;"></span>
</div>
<% if (ldapConfig && ldapConfig.last_sync) { %>
<p><strong>Letzte Synchronisation:</strong> <%= new Date(ldapConfig.last_sync).toLocaleString('de-DE') %></p>
<% } else { %>
<p><strong>Letzte Synchronisation:</strong> Noch keine Synchronisation durchgeführt</p>
<% } %>
</div>
<div class="ldap-sync-log" style="margin-top: 30px;">
<h3>Sync-Log (letzte 10 Einträge)</h3>
<table>
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Typ</th>
<th>Status</th>
<th>Benutzer synchronisiert</th>
<th>Fehlermeldung</th>
</tr>
</thead>
<tbody>
<% if (syncLogs && syncLogs.length > 0) { %>
<% syncLogs.forEach(function(log) { %>
<tr>
<td><%= new Date(log.sync_started_at).toLocaleString('de-DE') %></td>
<td><%= log.sync_type === 'manual' ? 'Manuell' : 'Automatisch' %></td>
<td>
<span class="role-badge role-<%= log.status === 'success' ? 'mitarbeiter' : 'admin' %>">
<%= log.status === 'success' ? 'Erfolg' : 'Fehler' %>
</span>
</td>
<td><%= log.users_synced %></td>
<td><%= log.error_message || '-' %></td>
</tr>
<% }); %>
<% } else { %>
<tr>
<td colspan="5" style="text-align: center;">Keine Log-Einträge vorhanden</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
</div>
<div class="mssql-config-section" style="margin-top: 40px;">
<div class="collapsible-header" onclick="toggleMssqlSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin: 0;">MSSQL-Projektsuche Konfiguration</h2>
<span id="mssqlToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="mssqlContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<div class="mssql-config-form">
<h3>MSSQL-Verbindungsdaten</h3>
<p style="margin-bottom: 20px; color: #666;">
Konfigurieren Sie hier die Verbindung zur MSSQL-Datenbank, aus der die Projektnummern ermittelt werden
(z.B. Tabelle <code>infra.dbo.KKOPF</code> und <code>KUNDE</code>).
</p>
<form id="mssqlConfigForm">
<div class="form-group">
<label for="mssqlServer">Server</label>
<input type="text" id="mssqlServer" name="server" placeholder="z.B. SERVER\\INSTANZ oder server.domain.local">
</div>
<div class="form-group">
<label for="mssqlDatabase">Datenbankname</label>
<input type="text" id="mssqlDatabase" name="database" placeholder="z.B. infra">
</div>
<div class="form-group">
<label for="mssqlUsername">Benutzername</label>
<input type="text" id="mssqlUsername" name="username" placeholder="Datenbank-Benutzer">
</div>
<div class="form-group">
<label for="mssqlPassword">Passwort</label>
<input type="password" id="mssqlPassword" name="password" placeholder="Leer lassen, um aktuelles Passwort zu behalten">
</div>
<% if (mssqlConfig && mssqlConfig.updated_at) { %>
<p style="margin-top: 10px; color: #666;">
<strong>Zuletzt geändert:</strong>
<%= new Date(mssqlConfig.updated_at).toLocaleString('de-DE') %>
</p>
<% } %>
<button type="submit" class="btn btn-primary">MSSQL-Konfiguration speichern</button>
<button type="button" id="mssqlTestConnectionBtn" class="btn btn-secondary" style="margin-left: 10px;">Verbindung testen</button>
<span id="mssqlTestStatus" style="margin-left: 10px;"></span>
</form>
</div>
</div>
</div>
<div class="options-section" style="margin-top: 40px;">
<div class="collapsible-header" onclick="toggleTimesheetMaintenanceSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin: 0;">Datenbankpflege doppelte Timesheet-Einträge</h2>
<span id="timesheetMaintenanceToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="timesheetMaintenanceContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<p style="margin-bottom: 15px; color: #666;">
Es werden alle Tage angezeigt, an denen ein Mitarbeiter mehr als einen Eintrag in der Tabelle <code>timesheet_entries</code> hat
(Schlüssel: Benutzer + Datum). Über diese Übersicht können Sie fehlerhafte Einträge gezielt löschen.
</p>
<button id="loadTimesheetDuplicatesBtn" class="btn btn-secondary" type="button" style="margin-bottom: 15px;">
Timesheet-Duplikate laden
</button>
<div id="timesheetDuplicatesContainer">
<p style="color: #888;">Noch keine Daten geladen. Klicken Sie auf „Timesheet-Duplikate laden“, um die Übersicht anzuzeigen.</p>
</div>
</div>
</div>
<div class="pdf-archive-section" style="margin-top: 40px;">
<div class="collapsible-header" onclick="togglePdfArchiveSection()" style="cursor: pointer; padding: 15px; background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;">
<h2 style="margin: 0;">PDF-Archiv (Timesheets)</h2>
<span id="pdfArchiveToggleIcon" style="font-size: 18px; transition: transform 0.3s;">▼</span>
</div>
<div id="pdfArchiveContent" style="display: none; padding: 20px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 4px 4px; background-color: #fff;">
<div class="form-row" style="display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-end;">
<div class="form-group" style="min-width: 180px;">
<label for="pdfYearSelect">Jahr</label>
<select id="pdfYearSelect" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"></select>
</div>
<div class="form-group" style="min-width: 180px;">
<label for="pdfUserSelect">User</label>
<select id="pdfUserSelect" disabled style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"></select>
</div>
<div class="form-group" style="min-width: 180px;">
<button id="pdfRefreshBtn" class="btn btn-secondary" type="button" style="width: 100%;">Aktualisieren</button>
</div>
</div>
<div id="pdfArchiveStatus" style="margin-top: 15px; color: #666;"></div>
<div id="pdfFilesContainer" style="margin-top: 15px; overflow-x: auto; max-width: 100%;"></div>
<div id="pdfPreviewContainer" style="display: none; margin-top: 25px;">
<h3 style="margin-top: 0;">Vorschau</h3>
<iframe id="pdfPreviewIframe" style="width: 100%; height: 650px; border: 1px solid #ddd; border-radius: 4px;"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/js/admin.js"></script>
<script>
// Benutzer anlegen Sektion ein-/ausklappen
function toggleAddUserSection() {
const content = document.getElementById('addUserContent');
const icon = document.getElementById('addUserToggleIcon');
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
// Benutzer-Liste Sektion ein-/ausklappen
function toggleUserListSection() {
const content = document.getElementById('userListContent');
const icon = document.getElementById('userListToggleIcon');
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
// LDAP-Sektion ein-/ausklappen
function toggleLDAPSection() {
const content = document.getElementById('ldapContent');
const icon = document.getElementById('ldapToggleIcon');
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
// Optionen-Sektion ein-/ausklappen
function toggleOptionsSection() {
const content = document.getElementById('optionsContent');
const icon = document.getElementById('optionsToggleIcon');
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
function toggleMssqlSection() {
const content = document.getElementById('mssqlContent');
const icon = document.getElementById('mssqlToggleIcon');
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
function toggleTimesheetMaintenanceSection() {
const content = document.getElementById('timesheetMaintenanceContent');
const icon = document.getElementById('timesheetMaintenanceToggleIcon');
if (!content) return;
if (content.style.display === 'none' || content.style.display === '') {
content.style.display = 'block';
if (icon) icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
if (icon) icon.style.transform = 'rotate(0deg)';
}
}
function togglePdfArchiveSection() {
const content = document.getElementById('pdfArchiveContent');
const icon = document.getElementById('pdfArchiveToggleIcon');
if (!content) return;
if (content.style.display === 'none' || content.style.display === '') {
content.style.display = 'block';
if (icon) icon.style.transform = 'rotate(180deg)';
} else {
content.style.display = 'none';
if (icon) icon.style.transform = 'rotate(0deg)';
}
}
// Rollenwechsel-Handler
document.addEventListener('DOMContentLoaded', function() {
const roleSwitcher = document.getElementById('roleSwitcher');
if (roleSwitcher) {
roleSwitcher.addEventListener('change', async function() {
const newRole = this.value;
try {
const response = await fetch('/api/user/switch-role', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ role: newRole })
});
const result = await response.json();
if (result.success) {
// Redirect basierend auf neuer Rolle
if (newRole === 'admin') {
window.location.href = '/admin';
} else if (newRole === 'verwaltung') {
window.location.href = '/verwaltung';
} else {
window.location.href = '/dashboard';
}
} else {
alert('Fehler beim Wechseln der Rolle: ' + (result.error || 'Unbekannter Fehler'));
// Wert zurücksetzen
this.value = '<%= user.currentRole || "admin" %>';
}
} catch (error) {
console.error('Fehler beim Rollenwechsel:', error);
alert('Fehler beim Wechseln der Rolle');
// Wert zurücksetzen
this.value = '<%= user.currentRole || "admin" %>';
}
});
}
});
</script>
<%- include('footer') %>
</body>
</html>