feat: refactor CSV filter & export section and enhance row styling in monthly view
All checks were successful
Build and Push Docker Image / build (push) Successful in 38s

This commit is contained in:
Felix Schlusche
2025-10-24 21:06:44 +02:00
parent fb33ea8144
commit 4bdd9310ea
2 changed files with 178 additions and 174 deletions

View File

@@ -1015,15 +1015,15 @@ function renderMonthlyView(entries) {
const entryType = entry.entryType || 'work';
// Row color based on entry type and location
let rowClass = 'hover:bg-gray-700';
let rowClass = 'hover:bg-slate-600/40 transition-colors';
if (entryType === 'vacation') {
rowClass = 'hover:bg-yellow-900 bg-yellow-950';
rowClass = 'hover:bg-yellow-800/50 bg-yellow-900/30 transition-colors';
} else if (entryType === 'flextime') {
rowClass = 'hover:bg-cyan-900 bg-cyan-950';
rowClass = 'hover:bg-cyan-800/50 bg-cyan-900/30 transition-colors';
} else if (location === 'home') {
rowClass = 'hover:bg-green-900 bg-green-950';
rowClass = 'hover:bg-green-800/50 bg-green-900/30 transition-colors';
} else if (weekend) {
rowClass = 'hover:bg-gray-700 bg-gray-700';
rowClass = 'hover:bg-slate-600/50 bg-slate-700/30 transition-colors';
}
@@ -1041,13 +1041,13 @@ function renderMonthlyView(entries) {
if (entryType === 'vacation') {
displayIcon = '<i data-lucide="plane" class="w-4 h-4 inline"></i>';
displayText = 'Urlaub';
displayTimes = `<td class="px-6 py-4 whitespace-nowrap text-sm text-center text-gray-400" colspan="3">
displayTimes = `<td class="px-4 py-3 whitespace-nowrap text-sm text-center text-gray-400" colspan="3">
<span class="italic">Urlaub</span>
</td>`;
} else if (entryType === 'flextime') {
displayIcon = '<i data-lucide="clock" class="w-4 h-4 inline"></i>';
displayText = 'Gleitzeit';
displayTimes = `<td class="px-6 py-4 whitespace-nowrap text-sm text-center text-gray-400" colspan="3">
displayTimes = `<td class="px-4 py-3 whitespace-nowrap text-sm text-center text-gray-400" colspan="3">
<span class="italic">Gleittag (8h)</span>
</td>`;
} else {
@@ -1063,15 +1063,15 @@ function renderMonthlyView(entries) {
: entry.endTime;
displayTimes = `
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-100 editable-cell"
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-100 editable-cell"
data-field="startTime" data-id="${entry.id}" data-value="${entry.startTime}">
${entry.startTime}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-100 ${isTimerRunning ? '' : 'editable-cell'}"
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-100 ${isTimerRunning ? '' : 'editable-cell'}"
${isTimerRunning ? '' : `data-field="endTime" data-id="${entry.id}" data-value="${entry.endTime}"`}>
${endTimeDisplay}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-100 ${isTimerRunning ? '' : 'editable-cell'}"
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-100 ${isTimerRunning ? '' : 'editable-cell'}"
${isTimerRunning ? `id="current-day-pause"` : `data-field="pauseMinutes" data-id="${entry.id}" data-value="${entry.pauseMinutes}"`}>
${entry.pauseMinutes}
</td>`;
@@ -1079,28 +1079,28 @@ function renderMonthlyView(entries) {
// Checkbox column (always present for consistent layout)
const checkboxCell = bulkEditMode ? `
<td class="px-2 py-4 whitespace-nowrap text-center">
<input type="checkbox" class="entry-checkbox w-5 h-5 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500"
<td class="px-2 py-3 whitespace-nowrap text-center">
<input type="checkbox" class="entry-checkbox w-4 h-4 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500"
data-id="${entry.id}" ${selectedEntries.has(entry.id) ? 'checked' : ''}>
</td>
` : '<td class="hidden"></td>';
row.innerHTML = checkboxCell + `
<td class="px-2 py-4 whitespace-nowrap text-sm font-medium ${weekend ? 'text-blue-400' : 'text-gray-100'}">${dayOfWeek}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-100">${formatDateDisplay(entry.date)}</td>
<td class="px-2 py-3 whitespace-nowrap text-sm font-medium ${weekend ? 'text-blue-400' : 'text-gray-100'}">${dayOfWeek}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-100">${formatDateDisplay(entry.date)}</td>
${displayTimes}
<td class="px-6 py-4 whitespace-nowrap text-sm font-semibold text-gray-100" id="${isToday ? 'current-day-net-hours' : ''}">${entry.netHours.toFixed(2)}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-center text-gray-100">
<td class="px-4 py-3 whitespace-nowrap text-sm font-semibold text-gray-100" id="${isToday ? 'current-day-net-hours' : ''}">${entry.netHours.toFixed(2)}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-center text-gray-100">
<span class="text-lg">${displayIcon}</span> ${displayText}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-center">
<td class="px-4 py-3 whitespace-nowrap text-sm text-center">
<div class="flex gap-2 justify-center">
${entryType === 'work' ? `
<button class="btn-edit inline-flex items-center justify-center w-8 h-8 text-blue-500 hover:text-blue-600 hover:bg-blue-500/10 rounded transition-all" data-id="${entry.id}" title="Bearbeiten">
<button class="btn-edit inline-flex items-center justify-center w-8 h-8 text-blue-400/80 hover:text-blue-400 hover:bg-blue-500/10 rounded transition-all" data-id="${entry.id}" title="Bearbeiten">
<i data-lucide="pencil" class="w-4 h-4"></i>
</button>
` : ''}
<button class="btn-delete inline-flex items-center justify-center w-8 h-8 text-red-500 hover:text-red-600 hover:bg-red-500/10 rounded transition-all" data-id="${entry.id}" title="Löschen">
<button class="btn-delete inline-flex items-center justify-center w-8 h-8 text-red-400/80 hover:text-red-400 hover:bg-red-500/10 rounded transition-all" data-id="${entry.id}" title="Löschen">
<i data-lucide="trash-2" class="w-4 h-4"></i>
</button>
</div>
@@ -1113,8 +1113,8 @@ function renderMonthlyView(entries) {
// Don't mark future days as red, only past workdays without entries
const isFutureDay = dateObj > today;
let emptyRowClass = weekend ? 'hover:bg-gray-700 bg-gray-700' :
isFutureDay ? 'hover:bg-gray-700' : 'hover:bg-gray-700 bg-red-950/40';
let emptyRowClass = weekend ? 'hover:bg-slate-600/50 bg-slate-700/30 transition-colors' :
isFutureDay ? 'hover:bg-slate-600/40 transition-colors' : 'hover:bg-slate-600/40 bg-red-900/30 transition-colors';
row.className = emptyRowClass;
@@ -1127,29 +1127,29 @@ function renderMonthlyView(entries) {
// Checkbox cell for empty days (in bulk edit mode)
const checkboxCell = bulkEditMode ? `
<td class="px-2 py-4 whitespace-nowrap text-center">
<input type="checkbox" class="empty-day-checkbox w-5 h-5 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500"
<td class="px-2 py-3 whitespace-nowrap text-center">
<input type="checkbox" class="empty-day-checkbox w-4 h-4 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500"
data-date="${dateISO}" ${selectedEntries.has(dateISO) ? 'checked' : ''}>
</td>
` : '<td class="hidden"></td>';
const colspan = bulkEditMode ? '5' : '5';
row.innerHTML = checkboxCell + `
<td class="px-2 py-4 whitespace-nowrap text-sm font-medium ${weekend ? 'text-blue-400' : 'text-gray-100'}">${dayOfWeek}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-100">${formatDateDisplay(dateISO)}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm ${holidayName ? 'text-blue-400 font-semibold' : 'text-gray-500'}" colspan="${colspan}">
<td class="px-2 py-3 whitespace-nowrap text-sm font-medium ${weekend ? 'text-blue-400' : 'text-gray-100'}">${dayOfWeek}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-100">${formatDateDisplay(dateISO)}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm ${holidayName ? 'text-blue-400 font-semibold' : 'text-gray-500'}" colspan="${colspan}">
<span class="italic">${displayText}</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-center">
<td class="px-4 py-3 whitespace-nowrap text-sm text-center">
<div class="flex gap-1 justify-center">
<button class="btn-add-work inline-flex items-center justify-center w-7 h-7 text-indigo-500 hover:text-indigo-600 hover:bg-indigo-500/10 rounded transition-all" data-date="${dateISO}" title="Arbeit eintragen">
<button class="btn-add-work inline-flex items-center justify-center w-7 h-7 text-indigo-400/80 hover:text-indigo-400 hover:bg-indigo-500/10 rounded transition-all" data-date="${dateISO}" title="Arbeit eintragen">
<i data-lucide="plus" class="w-4 h-4"></i>
</button>
${!weekend ? `
<button class="btn-add-vacation inline-flex items-center justify-center w-7 h-7 text-amber-500 hover:text-amber-600 hover:bg-amber-500/10 rounded transition-all" data-date="${dateISO}" title="Urlaub eintragen">
<button class="btn-add-vacation inline-flex items-center justify-center w-7 h-7 text-amber-400/80 hover:text-amber-400 hover:bg-amber-500/10 rounded transition-all" data-date="${dateISO}" title="Urlaub eintragen">
<i data-lucide="plane" class="w-4 h-4"></i>
</button>
<button class="btn-add-flextime inline-flex items-center justify-center w-7 h-7 text-cyan-500 hover:text-cyan-600 hover:bg-cyan-500/10 rounded transition-all" data-date="${dateISO}" title="Gleitzeit eintragen">
<button class="btn-add-flextime inline-flex items-center justify-center w-7 h-7 text-cyan-400/80 hover:text-cyan-400 hover:bg-cyan-500/10 rounded transition-all" data-date="${dateISO}" title="Gleitzeit eintragen">
<i data-lucide="clock" class="w-4 h-4"></i>
</button>
` : ''}
@@ -1290,10 +1290,14 @@ async function loadMonthlyView() {
(displayYear === today.getFullYear() && displayMonth >= today.getMonth());
const pdfButton = document.getElementById('btnExportPDF');
const pdfButtonMobile = document.getElementById('btnExportPDFMobile');
if (isCurrentOrFutureMonth) {
pdfButton.style.display = 'none';
if (pdfButtonMobile) pdfButtonMobile.style.display = 'none';
} else {
pdfButton.style.display = '';
if (pdfButtonMobile) pdfButtonMobile.style.display = '';
}
}