Release v0.40.0 Feiertagslogik
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v0.40.0
|
||||||
|
|
||||||
|
- Bundesland-Auswahl für Feiertage ergänzt
|
||||||
|
- Unterstützte Bundesländer: Bayern, Niedersachsen, Hamburg, Nordrhein-Westfalen
|
||||||
|
- Zusatzoption: Bayern inkl. Mariä Himmelfahrt
|
||||||
|
- Feiertage werden automatisch aus dem Datum berechnet
|
||||||
|
- Feiertage werden mit 0:00 Sollzeit bewertet
|
||||||
|
- Arbeit an Feiertagen zählt vollständig als Pluszeit
|
||||||
|
- Feiertagsspalte in Tagesdetails und CSV-Export ergänzt
|
||||||
|
|
||||||
|
## v0.30.0
|
||||||
|
|
||||||
|
- Sollzeit Montag bis Freitag = 8:00 Stunden
|
||||||
|
- Sollzeit Samstag und Sonntag = 0:00 Stunden
|
||||||
|
- Wochenendarbeit zählt vollständig als Pluszeit
|
||||||
@@ -1,34 +1,20 @@
|
|||||||
\# qplanner-arbeitszeit-auswertung
|
# qplanner-arbeitszeit-auswertung
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Browserbasierte Auswertung von qPlanner CSV-Exporten zur Berechnung von Plus- und Minusstunden.
|
Browserbasierte Auswertung von qPlanner CSV-Exporten zur Berechnung von Plus- und Minusstunden.
|
||||||
|
|
||||||
|
## Funktionen
|
||||||
|
|
||||||
|
- CSV-Upload im Browser
|
||||||
|
- Auswertung der Netto-Arbeitszeit
|
||||||
|
- Sollzeit Montag bis Freitag: 8:00 Stunden
|
||||||
|
- Sollzeit Samstag und Sonntag: 0:00 Stunden
|
||||||
|
- Gesetzliche Feiertage je Bundesland: 0:00 Stunden
|
||||||
|
- Unterstützte Bundesländer: Bayern, Niedersachsen, Hamburg, Nordrhein-Westfalen
|
||||||
|
- Zusatzoption: Bayern inkl. Mariä Himmelfahrt
|
||||||
|
- Monatsübersicht
|
||||||
|
- Tagesdetails inklusive Wochentag und Feiertag
|
||||||
|
- CSV-Export
|
||||||
|
|
||||||
\## Funktionen
|
## Datenschutz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\- CSV-Upload im Browser
|
|
||||||
|
|
||||||
\- Auswertung der Netto-Arbeitszeit
|
|
||||||
|
|
||||||
\- Sollzeit Montag bis Freitag: 8:00 Stunden
|
|
||||||
|
|
||||||
\- Sollzeit Samstag und Sonntag: 0:00 Stunden
|
|
||||||
|
|
||||||
\- Monatsübersicht
|
|
||||||
|
|
||||||
\- Tagesdetails
|
|
||||||
|
|
||||||
\- CSV-Export
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\## Datenschutz
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Die CSV-Datei wird ausschließlich lokal im Browser verarbeitet.
|
|
||||||
|
|
||||||
|
Die CSV-Datei wird ausschließlich lokal im Browser verarbeitet. Es findet kein Upload auf einen Server statt.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const fileInput = document.getElementById('csvFile');
|
const fileInput = document.getElementById('csvFile');
|
||||||
const dropZone = document.getElementById('dropZone');
|
const dropZone = document.getElementById('dropZone');
|
||||||
const targetTimeInput = document.getElementById('targetTime');
|
const targetTimeInput = document.getElementById('targetTime');
|
||||||
|
const federalStateSelect = document.getElementById('federalState');
|
||||||
const errorBox = document.getElementById('errorBox');
|
const errorBox = document.getElementById('errorBox');
|
||||||
const summary = document.getElementById('summary');
|
const summary = document.getElementById('summary');
|
||||||
const results = document.getElementById('results');
|
const results = document.getElementById('results');
|
||||||
@@ -21,6 +22,10 @@ targetTimeInput.addEventListener('change', () => {
|
|||||||
if (lastFileText) analyseCsv(lastFileText);
|
if (lastFileText) analyseCsv(lastFileText);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
federalStateSelect.addEventListener('change', () => {
|
||||||
|
if (lastFileText) analyseCsv(lastFileText);
|
||||||
|
});
|
||||||
|
|
||||||
exportButton.addEventListener('click', () => {
|
exportButton.addEventListener('click', () => {
|
||||||
if (lastResult) exportResultCsv(lastResult);
|
if (lastResult) exportResultCsv(lastResult);
|
||||||
});
|
});
|
||||||
@@ -70,15 +75,16 @@ function analyseCsv(text) {
|
|||||||
const dataRows = rows.slice(1).filter(row => row.some(cell => String(cell).trim() !== ''));
|
const dataRows = rows.slice(1).filter(row => row.some(cell => String(cell).trim() !== ''));
|
||||||
|
|
||||||
const targetMinutes = timeToMinutes(targetTimeInput.value || '08:00');
|
const targetMinutes = timeToMinutes(targetTimeInput.value || '08:00');
|
||||||
|
const federalState = federalStateSelect.value || 'NW';
|
||||||
const detectedFormat = detectFormat(headers);
|
const detectedFormat = detectFormat(headers);
|
||||||
|
|
||||||
let days;
|
let days;
|
||||||
if (detectedFormat === 'daily') {
|
if (detectedFormat === 'daily') {
|
||||||
days = analyseDailyFormat(headers, dataRows, targetMinutes);
|
days = analyseDailyFormat(headers, dataRows, targetMinutes, federalState);
|
||||||
formatHint.textContent = 'Format erkannt: Tagesauswertung. Montag bis Freitag haben Sollzeit, Samstag und Sonntag werden mit 0:00 Sollzeit berechnet. Zeilen ohne Arbeitszeit werden ignoriert.';
|
formatHint.textContent = `Format erkannt: Tagesauswertung. Montag bis Freitag haben Sollzeit, Samstag/Sonntag und Feiertage in ${stateLabel(federalState)} werden mit 0:00 Sollzeit berechnet. Zeilen ohne Arbeitszeit werden ignoriert.`;
|
||||||
} else if (detectedFormat === 'monthly') {
|
} else if (detectedFormat === 'monthly') {
|
||||||
days = analyseMonthlyFormat(headers, dataRows, targetMinutes);
|
days = analyseMonthlyFormat(headers, dataRows, targetMinutes, federalState);
|
||||||
formatHint.textContent = 'Format erkannt: Monatsauswertung. Arbeitszeiten werden aus dem Monatsblock gelesen.';
|
formatHint.textContent = `Format erkannt: Monatsauswertung. Arbeitszeiten werden aus dem Monatsblock gelesen. Wenn ein Datum erkannt wird, werden Wochenenden und Feiertage in ${stateLabel(federalState)} mit 0:00 Sollzeit berechnet.`;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Das CSV-Format wurde nicht erkannt. Benötigt wird entweder die Spalte "Tag" oder "Monat" plus "Dauer Arbeitstag".');
|
throw new Error('Das CSV-Format wurde nicht erkannt. Benötigt wird entweder die Spalte "Tag" oder "Monat" plus "Dauer Arbeitstag".');
|
||||||
}
|
}
|
||||||
@@ -93,7 +99,7 @@ function analyseCsv(text) {
|
|||||||
saldoMinutes: days.reduce((sum, day) => sum + day.saldoMinutes, 0)
|
saldoMinutes: days.reduce((sum, day) => sum + day.saldoMinutes, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
lastResult = { months, days, totals };
|
lastResult = { months, days, totals, federalState, federalStateLabel: stateLabel(federalState) };
|
||||||
render(lastResult);
|
render(lastResult);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError(error.message);
|
showError(error.message);
|
||||||
@@ -108,7 +114,7 @@ function detectFormat(headers) {
|
|||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
function analyseDailyFormat(headers, dataRows, targetMinutes) {
|
function analyseDailyFormat(headers, dataRows, targetMinutes, federalState) {
|
||||||
const dateIndex = headers.indexOf('Tag');
|
const dateIndex = headers.indexOf('Tag');
|
||||||
const startIndex = headers.indexOf('Arbeitstag Beginn');
|
const startIndex = headers.indexOf('Arbeitstag Beginn');
|
||||||
const endIndex = headers.indexOf('Arbeitstag Ende');
|
const endIndex = headers.indexOf('Arbeitstag Ende');
|
||||||
@@ -132,8 +138,9 @@ function analyseDailyFormat(headers, dataRows, targetMinutes) {
|
|||||||
end: cleanCell(row[endIndex]),
|
end: cleanCell(row[endIndex]),
|
||||||
workMinutes,
|
workMinutes,
|
||||||
weekday: weekdayNameFromDate(date),
|
weekday: weekdayNameFromDate(date),
|
||||||
targetMinutes: targetMinutesForDate(date, targetMinutes),
|
holiday: holidayNameForDate(date, federalState),
|
||||||
saldoMinutes: workMinutes - targetMinutesForDate(date, targetMinutes),
|
targetMinutes: targetMinutesForDate(date, targetMinutes, federalState),
|
||||||
|
saldoMinutes: workMinutes - targetMinutesForDate(date, targetMinutes, federalState),
|
||||||
breakOk: cleanCell(row[breakIndex]),
|
breakOk: cleanCell(row[breakIndex]),
|
||||||
warnings: cleanCell(row[warningIndex])
|
warnings: cleanCell(row[warningIndex])
|
||||||
});
|
});
|
||||||
@@ -141,7 +148,7 @@ function analyseDailyFormat(headers, dataRows, targetMinutes) {
|
|||||||
return days;
|
return days;
|
||||||
}
|
}
|
||||||
|
|
||||||
function analyseMonthlyFormat(headers, dataRows, targetMinutes) {
|
function analyseMonthlyFormat(headers, dataRows, targetMinutes, federalState) {
|
||||||
const monthIndex = headers.indexOf('Monat');
|
const monthIndex = headers.indexOf('Monat');
|
||||||
const durationIndex = headers.indexOf('Dauer Arbeitstag');
|
const durationIndex = headers.indexOf('Dauer Arbeitstag');
|
||||||
const stampIndex = headers.indexOf('Stempelzeit');
|
const stampIndex = headers.indexOf('Stempelzeit');
|
||||||
@@ -161,8 +168,9 @@ function analyseMonthlyFormat(headers, dataRows, targetMinutes) {
|
|||||||
end: '',
|
end: '',
|
||||||
workMinutes,
|
workMinutes,
|
||||||
weekday: weekdayNameFromDate(date),
|
weekday: weekdayNameFromDate(date),
|
||||||
targetMinutes: targetMinutesForDate(date, targetMinutes),
|
holiday: holidayNameForDate(date, federalState),
|
||||||
saldoMinutes: workMinutes - targetMinutesForDate(date, targetMinutes),
|
targetMinutes: targetMinutesForDate(date, targetMinutes, federalState),
|
||||||
|
saldoMinutes: workMinutes - targetMinutesForDate(date, targetMinutes, federalState),
|
||||||
breakOk: '',
|
breakOk: '',
|
||||||
warnings: ''
|
warnings: ''
|
||||||
});
|
});
|
||||||
@@ -172,13 +180,111 @@ function analyseMonthlyFormat(headers, dataRows, targetMinutes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function targetMinutesForDate(date, weekdayTargetMinutes) {
|
function targetMinutesForDate(date, weekdayTargetMinutes, federalState) {
|
||||||
const weekday = getWeekdayIndex(date);
|
const weekday = getWeekdayIndex(date);
|
||||||
// 0 = Sonntag, 6 = Samstag. Rufbereitschafts-/Wochenendarbeit zählt komplett als Pluszeit.
|
// 0 = Sonntag, 6 = Samstag. Rufbereitschafts-/Wochenendarbeit zählt komplett als Pluszeit.
|
||||||
if (weekday === 0 || weekday === 6) return 0;
|
if (weekday === 0 || weekday === 6) return 0;
|
||||||
|
if (holidayNameForDate(date, federalState)) return 0;
|
||||||
return weekdayTargetMinutes;
|
return weekdayTargetMinutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function stateLabel(state) {
|
||||||
|
const labels = {
|
||||||
|
NW: 'Nordrhein-Westfalen',
|
||||||
|
BY: 'Bayern',
|
||||||
|
BY_MH: 'Bayern inkl. Mariä Himmelfahrt',
|
||||||
|
NI: 'Niedersachsen',
|
||||||
|
HH: 'Hamburg'
|
||||||
|
};
|
||||||
|
return labels[state] || 'Nordrhein-Westfalen';
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseGermanDate(date) {
|
||||||
|
const match = String(date).match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
|
||||||
|
if (!match) return null;
|
||||||
|
return {
|
||||||
|
day: Number(match[1]),
|
||||||
|
month: Number(match[2]),
|
||||||
|
year: Number(match[3]),
|
||||||
|
key: `${match[3]}-${match[2]}-${match[1]}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function dateKeyFromDate(year, month, day) {
|
||||||
|
return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDaysKey(date, offset) {
|
||||||
|
const copy = new Date(date.getFullYear(), date.getMonth(), date.getDate() + offset);
|
||||||
|
return dateKeyFromDate(copy.getFullYear(), copy.getMonth() + 1, copy.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
function easterSunday(year) {
|
||||||
|
// Gaußsche Osterformel für den gregorianischen Kalender.
|
||||||
|
const a = year % 19;
|
||||||
|
const b = Math.floor(year / 100);
|
||||||
|
const c = year % 100;
|
||||||
|
const d = Math.floor(b / 4);
|
||||||
|
const e = b % 4;
|
||||||
|
const f = Math.floor((b + 8) / 25);
|
||||||
|
const g = Math.floor((b - f + 1) / 3);
|
||||||
|
const h = (19 * a + b - d - g + 15) % 30;
|
||||||
|
const i = Math.floor(c / 4);
|
||||||
|
const k = c % 4;
|
||||||
|
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
||||||
|
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
||||||
|
const month = Math.floor((h + l - 7 * m + 114) / 31);
|
||||||
|
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
||||||
|
return new Date(year, month - 1, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
function holidaysForYear(year, federalState) {
|
||||||
|
const easter = easterSunday(year);
|
||||||
|
const holidays = new Map();
|
||||||
|
|
||||||
|
const add = (month, day, name) => holidays.set(dateKeyFromDate(year, month, day), name);
|
||||||
|
const addRelative = (offset, name) => holidays.set(addDaysKey(easter, offset), name);
|
||||||
|
|
||||||
|
// Bundesweite Feiertage
|
||||||
|
add(1, 1, 'Neujahr');
|
||||||
|
addRelative(-2, 'Karfreitag');
|
||||||
|
addRelative(1, 'Ostermontag');
|
||||||
|
add(5, 1, 'Tag der Arbeit');
|
||||||
|
addRelative(39, 'Christi Himmelfahrt');
|
||||||
|
addRelative(50, 'Pfingstmontag');
|
||||||
|
add(10, 3, 'Tag der Deutschen Einheit');
|
||||||
|
add(12, 25, '1. Weihnachtstag');
|
||||||
|
add(12, 26, '2. Weihnachtstag');
|
||||||
|
|
||||||
|
if (federalState === 'BY' || federalState === 'BY_MH') {
|
||||||
|
add(1, 6, 'Heilige Drei Könige');
|
||||||
|
addRelative(60, 'Fronleichnam');
|
||||||
|
add(11, 1, 'Allerheiligen');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (federalState === 'BY_MH') {
|
||||||
|
add(8, 15, 'Mariä Himmelfahrt');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (federalState === 'NW') {
|
||||||
|
addRelative(60, 'Fronleichnam');
|
||||||
|
add(11, 1, 'Allerheiligen');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (federalState === 'NI' || federalState === 'HH') {
|
||||||
|
add(10, 31, 'Reformationstag');
|
||||||
|
}
|
||||||
|
|
||||||
|
return holidays;
|
||||||
|
}
|
||||||
|
|
||||||
|
function holidayNameForDate(date, federalState) {
|
||||||
|
const parsed = parseGermanDate(date);
|
||||||
|
if (!parsed) return '';
|
||||||
|
return holidaysForYear(parsed.year, federalState).get(parsed.key) || '';
|
||||||
|
}
|
||||||
|
|
||||||
function getWeekdayIndex(date) {
|
function getWeekdayIndex(date) {
|
||||||
const match = String(date).match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
|
const match = String(date).match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
@@ -330,6 +436,7 @@ function render(result) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>${escapeHtml(day.date)}</td>
|
<td>${escapeHtml(day.date)}</td>
|
||||||
<td>${escapeHtml(day.weekday || '')}</td>
|
<td>${escapeHtml(day.weekday || '')}</td>
|
||||||
|
<td>${escapeHtml(day.holiday || '')}</td>
|
||||||
<td>${escapeHtml(day.start || '')}</td>
|
<td>${escapeHtml(day.start || '')}</td>
|
||||||
<td>${escapeHtml(day.end || '')}</td>
|
<td>${escapeHtml(day.end || '')}</td>
|
||||||
<td>${formatDuration(day.workMinutes)}</td>
|
<td>${formatDuration(day.workMinutes)}</td>
|
||||||
@@ -343,14 +450,14 @@ function render(result) {
|
|||||||
|
|
||||||
function exportResultCsv(result) {
|
function exportResultCsv(result) {
|
||||||
const rows = [
|
const rows = [
|
||||||
['Bereich', 'Monat/Datum', 'Arbeitstage', 'Arbeitszeit', 'Sollzeit', 'Saldo'],
|
['Bereich', 'Monat/Datum', 'Arbeitstage', 'Arbeitszeit', 'Sollzeit', 'Saldo', 'Bundesland'],
|
||||||
['Gesamt', '', result.totals.days, formatDuration(result.totals.workMinutes), formatDuration(result.totals.targetMinutes), formatDuration(result.totals.saldoMinutes, true)],
|
['Gesamt', '', result.totals.days, formatDuration(result.totals.workMinutes), formatDuration(result.totals.targetMinutes), formatDuration(result.totals.saldoMinutes, true), result.federalStateLabel || ''],
|
||||||
[],
|
[],
|
||||||
['Monat', 'Monat/Datum', 'Arbeitstage', 'Arbeitszeit', 'Sollzeit', 'Saldo'],
|
['Monat', 'Monat/Datum', 'Arbeitstage', 'Arbeitszeit', 'Sollzeit', 'Saldo'],
|
||||||
...result.months.map(m => ['Monat', m.month, m.days, formatDuration(m.workMinutes), formatDuration(m.targetMinutes), formatDuration(m.saldoMinutes, true)]),
|
...result.months.map(m => ['Monat', m.month, m.days, formatDuration(m.workMinutes), formatDuration(m.targetMinutes), formatDuration(m.saldoMinutes, true)]),
|
||||||
[],
|
[],
|
||||||
['Tag', 'Datum', 'Wochentag', 'Beginn', 'Ende', 'Arbeitszeit', 'Sollzeit', 'Saldo', 'Ruhepause', 'Warnungen'],
|
['Tag', 'Datum', 'Wochentag', 'Feiertag', 'Beginn', 'Ende', 'Arbeitszeit', 'Sollzeit', 'Saldo', 'Ruhepause', 'Warnungen'],
|
||||||
...result.days.map(d => ['Tag', d.date, d.weekday || '', d.start, d.end, formatDuration(d.workMinutes), formatDuration(d.targetMinutes), formatDuration(d.saldoMinutes, true), d.breakOk, d.warnings])
|
...result.days.map(d => ['Tag', d.date, d.weekday || '', d.holiday || '', d.start, d.end, formatDuration(d.workMinutes), formatDuration(d.targetMinutes), formatDuration(d.saldoMinutes, true), d.breakOk, d.warnings])
|
||||||
];
|
];
|
||||||
|
|
||||||
const csv = rows.map(row => row.map(csvEscape).join(';')).join('\n');
|
const csv = rows.map(row => row.map(csvEscape).join(';')).join('\n');
|
||||||
|
|||||||
+14
-2
@@ -12,13 +12,24 @@
|
|||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">CSV-Auswertung</p>
|
<p class="eyebrow">CSV-Auswertung</p>
|
||||||
<h1>Arbeitszeit-Saldo berechnen</h1>
|
<h1>Arbeitszeit-Saldo berechnen</h1>
|
||||||
<p class="intro">CSV-Datei hochladen, Netto-Arbeitszeiten auslesen und Plus-/Minusstunden berechnen: Montag bis Freitag mit 8:00 Stunden Sollzeit, Samstag/Sonntag mit 0:00 Sollzeit.</p>
|
<p class="intro">CSV-Datei hochladen, Netto-Arbeitszeiten auslesen und Plus-/Minusstunden berechnen: Montag bis Freitag mit 8:00 Stunden Sollzeit, Samstag/Sonntag und gesetzliche Feiertage mit 0:00 Sollzeit.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings" aria-label="Einstellungen">
|
<div class="settings" aria-label="Einstellungen">
|
||||||
<label>
|
<label>
|
||||||
Sollzeit pro Arbeitstag
|
Sollzeit pro Arbeitstag
|
||||||
<input id="targetTime" type="time" value="08:00" step="60">
|
<input id="targetTime" type="time" value="08:00" step="60">
|
||||||
<small>Gilt für Montag bis Freitag. Samstag/Sonntag = 0:00.</small>
|
<small>Gilt für Montag bis Freitag. Samstag/Sonntag und Feiertage = 0:00.</small>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Bundesland / Feiertage
|
||||||
|
<select id="federalState">
|
||||||
|
<option value="NW" selected>Nordrhein-Westfalen</option>
|
||||||
|
<option value="BY">Bayern</option>
|
||||||
|
<option value="BY_MH">Bayern inkl. Mariä Himmelfahrt</option>
|
||||||
|
<option value="NI">Niedersachsen</option>
|
||||||
|
<option value="HH">Hamburg</option>
|
||||||
|
</select>
|
||||||
|
<small>Feiertage werden automatisch aus dem Datum berechnet.</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -82,6 +93,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Datum</th>
|
<th>Datum</th>
|
||||||
<th>Wochentag</th>
|
<th>Wochentag</th>
|
||||||
|
<th>Feiertag</th>
|
||||||
<th>Beginn</th>
|
<th>Beginn</th>
|
||||||
<th>Ende</th>
|
<th>Ende</th>
|
||||||
<th>Arbeitszeit</th>
|
<th>Arbeitszeit</th>
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ h1 {
|
|||||||
border: 1px solid #dde5f2;
|
border: 1px solid #dde5f2;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
min-width: 280px;
|
||||||
|
display: grid;
|
||||||
|
gap: 14px;
|
||||||
box-shadow: 0 12px 30px rgba(29, 45, 68, .08);
|
box-shadow: 0 12px 30px rgba(29, 45, 68, .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +63,8 @@ h1 {
|
|||||||
color: #566277;
|
color: #566277;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings input {
|
.settings input,
|
||||||
|
.settings select {
|
||||||
border: 1px solid #cbd5e1;
|
border: 1px solid #cbd5e1;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
|
|||||||
Reference in New Issue
Block a user