This commit is contained in:
2026-01-30 22:24:36 +01:00
parent 3d02fd56ea
commit c6421049c8
6 changed files with 78 additions and 47 deletions

View File

@@ -24,10 +24,10 @@ body {
/* Navbar */ /* Navbar */
.navbar { .navbar {
background-color: #2c3e50; background-color: #0066FF;
color: white; color: white;
padding: 15px 0; padding: 15px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
} }
.navbar .container { .navbar .container {
@@ -104,6 +104,15 @@ body {
background-color: #7f8c8d; background-color: #7f8c8d;
} }
.btn-logout {
background-color: #e74c3c;
color: white;
}
.btn-logout:hover {
background-color: #c0392b;
}
.btn-success { .btn-success {
background-color: #27ae60; background-color: #27ae60;
color: white; color: white;
@@ -146,14 +155,14 @@ body {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
min-height: 100vh; min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: #0066FF;
} }
.login-box { .login-box {
background: white; background: white;
padding: 40px; padding: 40px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
width: 100%; width: 100%;
max-width: 400px; max-width: 400px;
} }
@@ -242,7 +251,7 @@ body {
border-color: #3498db; border-color: #3498db;
background-color: #f0f8ff; background-color: #f0f8ff;
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
} }
.role-checkbox-label-small { .role-checkbox-label-small {
@@ -259,7 +268,7 @@ body {
flex-shrink: 0; flex-shrink: 0;
} }
.role-checkbox-input:checked + .role-checkbox-text { .role-checkbox-input:checked+.role-checkbox-text {
font-weight: 600; font-weight: 600;
color: #2c3e50; color: #2c3e50;
} }
@@ -308,9 +317,10 @@ body {
background: white; background: white;
padding: 30px; padding: 30px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
flex: 1; flex: 1;
min-width: 0; /* Ermöglicht Flexbox-Shrinking */ min-width: 0;
/* Ermöglicht Flexbox-Shrinking */
} }
/* User Stats Panel */ /* User Stats Panel */
@@ -318,7 +328,7 @@ body {
background: white; background: white;
padding: 20px; padding: 20px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
width: 280px; width: 280px;
flex-shrink: 0; flex-shrink: 0;
box-sizing: border-box; box-sizing: border-box;
@@ -454,7 +464,7 @@ table input[type="text"] {
background: white; background: white;
padding: 30px; padding: 30px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
width: 100%; width: 100%;
} }
@@ -577,7 +587,7 @@ table input[type="text"] {
background: white; background: white;
padding: 30px 40px; padding: 30px 40px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
width: 100%; width: 100%;
} }
@@ -768,7 +778,7 @@ table input[type="text"] {
z-index: 1; z-index: 1;
} }
.pdf-iframe:not([src=""]) ~ .pdf-fallback { .pdf-iframe:not([src=""])~.pdf-fallback {
display: none; display: none;
} }
@@ -917,7 +927,7 @@ table input[type="text"] {
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 8px; border-radius: 8px;
padding: 25px 30px; padding: 25px 30px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px; margin-bottom: 20px;
} }
@@ -997,14 +1007,14 @@ table input[type="text"] {
.dashboard-layout { .dashboard-layout {
flex-direction: column; flex-direction: column;
} }
.user-stats-panel { .user-stats-panel {
width: 100%; width: 100%;
display: flex; display: flex;
gap: 15px; gap: 15px;
flex-wrap: wrap; flex-wrap: wrap;
} }
.stat-card { .stat-card {
flex: 1; flex: 1;
min-width: 200px; min-width: 200px;
@@ -1016,39 +1026,39 @@ table input[type="text"] {
.dashboard-container { .dashboard-container {
padding: 15px; padding: 15px;
} }
.form-row { .form-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.week-selector { .week-selector {
flex-direction: column; flex-direction: column;
gap: 15px; gap: 15px;
} }
table { table {
font-size: 12px; font-size: 12px;
} }
table th, table th,
table td { table td {
padding: 8px; padding: 8px;
} }
.user-stats-panel { .user-stats-panel {
flex-direction: column; flex-direction: column;
} }
.stat-card { .stat-card {
width: 100%; width: 100%;
} }
.activity-row { .activity-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.overtime-vacation-controls { .overtime-vacation-controls {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
} }

View File

@@ -210,25 +210,15 @@ function registerVerwaltungRoutes(app) {
vacationDays += 0.5; vacationDays += 0.5;
vacationHours += 4; // Halber Tag = 4 Stunden vacationHours += 4; // Halber Tag = 4 Stunden
// Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein
// WICHTIG: total_hours enthält bereits Wochenend-Prozentsätze (aus timesheet.js)
if (entry.total_hours) { if (entry.total_hours) {
let hours = entry.total_hours; totalHours += parseFloat(entry.total_hours) || 0;
// Wochenend-Prozentsatz anwenden (nur auf tatsächlich gearbeitete Stunden)
const weekendPercentage = getWeekendPercentage(entry.date);
if (weekendPercentage >= 100 && hours > 0 && !entry.sick_status) {
hours = hours * (weekendPercentage / 100);
}
totalHours += hours;
} }
} else { } else {
// Kein Urlaub - zähle nur Arbeitsstunden // Kein Urlaub - zähle nur Arbeitsstunden
// WICHTIG: total_hours enthält bereits Wochenend-Prozentsätze (aus timesheet.js)
if (entry.total_hours) { if (entry.total_hours) {
let hours = entry.total_hours; totalHours += parseFloat(entry.total_hours) || 0;
// Wochenend-Prozentsatz anwenden (nur auf tatsächlich gearbeitete Stunden, nicht auf Krankheit)
const weekendPercentage = getWeekendPercentage(entry.date);
if (weekendPercentage > 0 && hours > 0 && !entry.sick_status) {
hours = hours * (1 + weekendPercentage / 100);
}
totalHours += hours;
} }
} }
}); });

View File

@@ -24,7 +24,7 @@
<% }); %> <% }); %>
</select> </select>
<% } %> <% } %>
<a href="/logout" class="btn btn-secondary">Abmelden</a> <a href="/logout" class="btn btn-logout">Abmelden</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -25,7 +25,7 @@
<% }); %> <% }); %>
</select> </select>
<% } %> <% } %>
<a href="/logout" class="btn btn-secondary">Abmelden</a> <a href="/logout" class="btn btn-logout">Abmelden</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -98,6 +98,12 @@
font-weight: 600; font-weight: 600;
color: #2c3e50; color: #2c3e50;
} }
.summary-value.overtime-positive {
color: #27ae60 !important;
}
.summary-value.overtime-negative {
color: #e74c3c !important;
}
</style> </style>
</head> </head>
<body> <body>
@@ -117,7 +123,7 @@
<% }); %> <% }); %>
</select> </select>
<% } %> <% } %>
<a href="/logout" class="btn btn-secondary">Abmelden</a> <a href="/logout" class="btn btn-logout">Abmelden</a>
</div> </div>
</div> </div>
</div> </div>
@@ -142,6 +148,10 @@
<span class="summary-label">Verbleibend:</span> <span class="summary-label">Verbleibend:</span>
<span class="summary-value" id="remainingOvertime">-</span> <span class="summary-value" id="remainingOvertime">-</span>
</div> </div>
<div class="summary-item" id="offsetItem" style="display: none;">
<span class="summary-label">Manuelle Korrektur (Verwaltung):</span>
<span class="summary-value" id="overtimeOffset">-</span>
</div>
</div> </div>
<div id="loading" class="loading">Lade Daten...</div> <div id="loading" class="loading">Lade Daten...</div>
@@ -231,17 +241,38 @@
totalOvertime += week.overtime_hours; totalOvertime += week.overtime_hours;
totalOvertimeTaken += week.overtime_taken; totalOvertimeTaken += week.overtime_taken;
}); });
const remainingOvertime = totalOvertime - totalOvertimeTaken + (data.overtime_offset_hours || 0); const overtimeOffset = data.overtime_offset_hours || 0;
const remainingOvertime = totalOvertime - totalOvertimeTaken + overtimeOffset;
// Zusammenfassung anzeigen // Zusammenfassung anzeigen
document.getElementById('totalOvertime').textContent = const totalOvertimeEl = document.getElementById('totalOvertime');
totalOvertimeEl.textContent =
(totalOvertime >= 0 ? '+' : '') + totalOvertime.toFixed(2) + ' h'; (totalOvertime >= 0 ? '+' : '') + totalOvertime.toFixed(2) + ' h';
document.getElementById('totalOvertimeTaken').textContent = totalOvertimeEl.className =
'summary-value ' + (totalOvertime >= 0 ? 'overtime-positive' : 'overtime-negative');
const totalOvertimeTakenEl = document.getElementById('totalOvertimeTaken');
totalOvertimeTakenEl.textContent =
totalOvertimeTaken.toFixed(2) + ' h'; totalOvertimeTaken.toFixed(2) + ' h';
document.getElementById('remainingOvertime').textContent = totalOvertimeTakenEl.className = 'summary-value overtime-positive';
const remainingOvertimeEl = document.getElementById('remainingOvertime');
remainingOvertimeEl.textContent =
(remainingOvertime >= 0 ? '+' : '') + remainingOvertime.toFixed(2) + ' h'; (remainingOvertime >= 0 ? '+' : '') + remainingOvertime.toFixed(2) + ' h';
document.getElementById('remainingOvertime').className = remainingOvertimeEl.className =
'summary-value ' + (remainingOvertime >= 0 ? 'overtime-positive' : 'overtime-negative'); 'summary-value ' + (remainingOvertime >= 0 ? 'overtime-positive' : 'overtime-negative');
// Manuelle Korrektur anzeigen (nur wenn vorhanden)
const offsetItem = document.getElementById('offsetItem');
const offsetValue = document.getElementById('overtimeOffset');
if (overtimeOffset !== 0) {
offsetValue.textContent = (overtimeOffset >= 0 ? '+' : '') + overtimeOffset.toFixed(2) + ' h';
offsetValue.className = 'summary-value ' + (overtimeOffset >= 0 ? 'overtime-positive' : 'overtime-negative');
offsetItem.style.display = 'flex';
} else {
offsetItem.style.display = 'none';
}
summaryBoxEl.style.display = 'block'; summaryBoxEl.style.display = 'block';
// Tabelle füllen // Tabelle füllen

View File

@@ -24,7 +24,7 @@
<% }); %> <% }); %>
</select> </select>
<% } %> <% } %>
<a href="/logout" class="btn btn-secondary">Abmelden</a> <a href="/logout" class="btn btn-logout">Abmelden</a>
</div> </div>
</div> </div>
</div> </div>