186 lines
7.4 KiB
Plaintext
186 lines
7.4 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Projektauswertung - Verwaltung</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>Projektauswertung - Verwaltung</h1>
|
|
</div>
|
|
<div class="nav-right">
|
|
<span>Verwaltung: <%= 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="container verwaltung-container">
|
|
<div class="verwaltung-panel">
|
|
<h2>Projektauswertung nach Mitarbeitern</h2>
|
|
<p>Geben Sie eine Projektnummer ein, um alle erfassten Stunden pro Mitarbeiter für dieses Projekt auszuwerten.</p>
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
<a href="/verwaltung" class="btn btn-secondary">« Zurück zur Verwaltung</a>
|
|
</div>
|
|
|
|
<form method="GET" action="/verwaltung/projektauswertung" class="projekt-filter-form" style="margin-bottom: 20px;">
|
|
<div class="form-group">
|
|
<label for="projectNumber"><strong>Projektnummer</strong></label>
|
|
<input
|
|
type="text"
|
|
id="projectNumber"
|
|
name="project"
|
|
value="<%= projectNumber || '' %>"
|
|
class="form-control"
|
|
placeholder="z. B. 12345"
|
|
required
|
|
style="max-width: 240px;">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Auswerten</button>
|
|
</form>
|
|
|
|
<% if (projectNumber && !hasResults) { %>
|
|
<div class="empty-state">
|
|
<p>Für das Projekt <strong><%= projectNumber %></strong> wurden keine Stunden gefunden.</p>
|
|
</div>
|
|
<% } %>
|
|
|
|
<% if (hasResults) { %>
|
|
<h3>Ergebnis für Projekt <span style="white-space: nowrap;"><%= projectNumber %></span></h3>
|
|
<table class="timesheet-table" style="margin-top: 15px;">
|
|
<thead>
|
|
<tr>
|
|
<th>Mitarbeiter</th>
|
|
<th style="text-align: right;">Gesamtzeit (h:mm)</th>
|
|
<th style="width: 1%; white-space: nowrap;"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% results.forEach(function(row) {
|
|
const activities = (breakdownByUser && breakdownByUser[row.userId]) || [];
|
|
%>
|
|
<tr class="employee-summary-row" data-user-id="<%= row.userId %>">
|
|
<td><strong><%= row.firstname %> <%= row.lastname %></strong></td>
|
|
<td style="text-align: right;"><%= row.totalHoursFormatted %> h</td>
|
|
<td style="text-align: right;">
|
|
<% if (activities.length > 0) { %>
|
|
<button
|
|
type="button"
|
|
class="btn btn-secondary btn-sm toggle-details-btn"
|
|
data-user-id="<%= row.userId %>">
|
|
Details
|
|
</button>
|
|
<% } %>
|
|
</td>
|
|
</tr>
|
|
<% if (activities.length > 0) { %>
|
|
<tr class="employee-details-row" data-user-id="<%= row.userId %>" style="display: none; background-color: #fafafa;">
|
|
<td colspan="3">
|
|
<div style="padding: 10px 5px 5px 5px;">
|
|
<strong>Aufschlüsselung für <%= row.firstname %> <%= row.lastname %>:</strong>
|
|
<table class="timesheet-table" style="margin-top: 8px;">
|
|
<thead>
|
|
<tr>
|
|
<th>Datum</th>
|
|
<th>Tätigkeit</th>
|
|
<th style="text-align: right;">Stunden (h:mm)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% activities.forEach(function(a) { %>
|
|
<tr>
|
|
<td><%= a.date %></td>
|
|
<td><%= a.description && a.description.trim() !== '' ? a.description : '-' %></td>
|
|
<td style="text-align: right;"><%= a.formatted %> h</td>
|
|
</tr>
|
|
<% }); %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<% } %>
|
|
<% }); %>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<th>Gesamt Projektstunden</th>
|
|
<th style="text-align: right;"><%= totalProjectHoursFormatted %> h</th>
|
|
<th></th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
<% } %>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Rollenwechsel-Handler (analog zu Verwaltung-Ansicht) und Details-Collapsibles
|
|
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) {
|
|
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'));
|
|
this.value = '<%= user.currentRole || "verwaltung" %>';
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Rollenwechsel:', error);
|
|
alert('Fehler beim Wechseln der Rolle');
|
|
this.value = '<%= user.currentRole || "verwaltung" %>';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Mitarbeiter-Details (Aktivitäten) ein-/ausklappen
|
|
document.querySelectorAll('.toggle-details-btn').forEach(function(btn) {
|
|
btn.addEventListener('click', function() {
|
|
const userId = this.dataset.userId;
|
|
const row = document.querySelector('.employee-details-row[data-user-id="' + userId + '"]');
|
|
if (!row) return;
|
|
const isHidden = row.style.display === 'none' || row.style.display === '';
|
|
row.style.display = isHidden ? 'table-row' : 'none';
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
<%- include('footer') %>
|
|
</body>
|
|
</html>
|
|
|