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

View File

@@ -210,25 +210,15 @@ function registerVerwaltungRoutes(app) {
vacationDays += 0.5;
vacationHours += 4; // Halber Tag = 4 Stunden
// 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) {
let hours = entry.total_hours;
// 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;
totalHours += parseFloat(entry.total_hours) || 0;
}
} else {
// Kein Urlaub - zähle nur Arbeitsstunden
// WICHTIG: total_hours enthält bereits Wochenend-Prozentsätze (aus timesheet.js)
if (entry.total_hours) {
let hours = entry.total_hours;
// 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;
totalHours += parseFloat(entry.total_hours) || 0;
}
}
});

View File

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

View File

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

View File

@@ -98,6 +98,12 @@
font-weight: 600;
color: #2c3e50;
}
.summary-value.overtime-positive {
color: #27ae60 !important;
}
.summary-value.overtime-negative {
color: #e74c3c !important;
}
</style>
</head>
<body>
@@ -117,7 +123,7 @@
<% }); %>
</select>
<% } %>
<a href="/logout" class="btn btn-secondary">Abmelden</a>
<a href="/logout" class="btn btn-logout">Abmelden</a>
</div>
</div>
</div>
@@ -142,6 +148,10 @@
<span class="summary-label">Verbleibend:</span>
<span class="summary-value" id="remainingOvertime">-</span>
</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 id="loading" class="loading">Lade Daten...</div>
@@ -231,17 +241,38 @@
totalOvertime += week.overtime_hours;
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
document.getElementById('totalOvertime').textContent =
const totalOvertimeEl = document.getElementById('totalOvertime');
totalOvertimeEl.textContent =
(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';
document.getElementById('remainingOvertime').textContent =
totalOvertimeTakenEl.className = 'summary-value overtime-positive';
const remainingOvertimeEl = document.getElementById('remainingOvertime');
remainingOvertimeEl.textContent =
(remainingOvertime >= 0 ? '+' : '') + remainingOvertime.toFixed(2) + ' h';
document.getElementById('remainingOvertime').className =
remainingOvertimeEl.className =
'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';
// Tabelle füllen

View File

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