fix: improve holiday name retrieval by comparing year, month, and day directly to avoid timezone issues
refactor: change exported variables to local scope in state management for better encapsulation
This commit is contained in:
@@ -129,11 +129,16 @@ function getPublicHolidays(year, bundesland) {
|
|||||||
*/
|
*/
|
||||||
function getHolidayName(date) {
|
function getHolidayName(date) {
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
|
const month = date.getMonth();
|
||||||
|
const day = date.getDate();
|
||||||
|
|
||||||
const holidays = getPublicHolidays(year, currentBundesland);
|
const holidays = getPublicHolidays(year, currentBundesland);
|
||||||
|
|
||||||
const dateStr = date.toISOString().split('T')[0];
|
// Compare year, month, and day directly (avoid timezone issues)
|
||||||
const holiday = holidays.find(h => {
|
const holiday = holidays.find(h => {
|
||||||
return h.date.toISOString().split('T')[0] === dateStr;
|
return h.date.getFullYear() === year &&
|
||||||
|
h.date.getMonth() === month &&
|
||||||
|
h.date.getDate() === day;
|
||||||
});
|
});
|
||||||
|
|
||||||
return holiday ? holiday.name : null;
|
return holiday ? holiday.name : null;
|
||||||
|
|||||||
@@ -1,38 +1,18 @@
|
|||||||
// ============================================
|
// ============================================
|
||||||
// STATE & VARIABLES
|
// STATE & VARIABLES (additional to state.js)
|
||||||
// ============================================
|
// ============================================
|
||||||
let currentEditingId = null;
|
|
||||||
let datePicker = null;
|
|
||||||
let startTimePicker = null;
|
|
||||||
let endTimePicker = null;
|
|
||||||
let filterFromPicker = null;
|
|
||||||
let filterToPicker = null;
|
|
||||||
let manualStartTimePicker = null;
|
let manualStartTimePicker = null;
|
||||||
|
|
||||||
// Timer state
|
// Additional timer state (beyond state.js)
|
||||||
let timerInterval = null;
|
|
||||||
let timerStartTime = null;
|
|
||||||
let timerPausedDuration = 0; // Total paused time in seconds
|
|
||||||
let isPaused = false;
|
|
||||||
let pauseTimeout = null;
|
|
||||||
let pauseStartElapsed = 0; // Elapsed time when pause started (to freeze display)
|
let pauseStartElapsed = 0; // Elapsed time when pause started (to freeze display)
|
||||||
let pauseEndTime = 0; // Timestamp when pause will end (for countdown)
|
let pauseEndTime = 0; // Timestamp when pause will end (for countdown)
|
||||||
let timerStartTimeString = ''; // Start time as string (HH:MM) for display
|
let timerStartTimeString = ''; // Start time as string (HH:MM) for display
|
||||||
let currentEntryId = null; // ID of today's entry being timed
|
|
||||||
|
|
||||||
// Current month display state
|
|
||||||
let displayYear = new Date().getFullYear();
|
|
||||||
let displayMonth = new Date().getMonth(); // 0-11
|
|
||||||
|
|
||||||
// Current view state
|
// Current view state
|
||||||
let currentView = 'monthly'; // 'monthly' or 'filter'
|
let currentView = 'monthly'; // 'monthly' or 'filter'
|
||||||
let currentFilterFrom = null;
|
let currentFilterFrom = null;
|
||||||
let currentFilterTo = null;
|
let currentFilterTo = null;
|
||||||
|
|
||||||
// Bulk edit state
|
|
||||||
let bulkEditMode = false;
|
|
||||||
let selectedEntries = new Set();
|
|
||||||
|
|
||||||
// Settings state
|
// Settings state
|
||||||
let currentBundesland = 'BW'; // Default: Baden-Württemberg
|
let currentBundesland = 'BW'; // Default: Baden-Württemberg
|
||||||
let totalVacationDays = 30; // Default vacation days per year
|
let totalVacationDays = 30; // Default vacation days per year
|
||||||
@@ -2109,7 +2089,10 @@ async function bulkExportPDF() {
|
|||||||
|
|
||||||
// Count workdays based on selected entries only
|
// Count workdays based on selected entries only
|
||||||
selectedDates.forEach(dateISO => {
|
selectedDates.forEach(dateISO => {
|
||||||
const dateObj = new Date(dateISO);
|
// Parse date correctly to avoid timezone issues
|
||||||
|
const [year, month, day] = dateISO.split('-').map(Number);
|
||||||
|
const dateObj = new Date(year, month - 1, day);
|
||||||
|
|
||||||
const isVacation = vacationDaysSet.has(dateISO);
|
const isVacation = vacationDaysSet.has(dateISO);
|
||||||
const isFlextime = flextimeDaysSet.has(dateISO);
|
const isFlextime = flextimeDaysSet.has(dateISO);
|
||||||
const isWeekendHoliday = isWeekendOrHoliday(dateObj);
|
const isWeekendHoliday = isWeekendOrHoliday(dateObj);
|
||||||
@@ -2975,8 +2958,19 @@ async function handleExportPDF() {
|
|||||||
|
|
||||||
// Calculate statistics
|
// Calculate statistics
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
|
today.setHours(23, 59, 59, 999); // Set to end of day to include today
|
||||||
|
|
||||||
// Count workdays (excluding weekends and holidays, only up to today)
|
// Find the last entry date to calculate workdays up to (parse correctly to avoid timezone issues)
|
||||||
|
let lastEntryDate = today;
|
||||||
|
if (entries.length > 0) {
|
||||||
|
const sortedEntries = entries.sort((a, b) => b.date.localeCompare(a.date));
|
||||||
|
const lastDateStr = sortedEntries[0].date; // "2025-10-22"
|
||||||
|
const [year, month, day] = lastDateStr.split('-').map(Number);
|
||||||
|
lastEntryDate = new Date(year, month - 1, day, 23, 59, 59, 999);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count workdays (excluding weekends and holidays, up to last entry or today, whichever is later)
|
||||||
|
const countUntil = lastEntryDate > today ? lastEntryDate : today;
|
||||||
let workdaysPassed = 0;
|
let workdaysPassed = 0;
|
||||||
let totalWorkdaysInMonth = 0;
|
let totalWorkdaysInMonth = 0;
|
||||||
|
|
||||||
@@ -3008,13 +3002,13 @@ async function handleExportPDF() {
|
|||||||
if (!isWeekendHoliday && !isVacation) {
|
if (!isWeekendHoliday && !isVacation) {
|
||||||
// Normal workday (excluding vacation days)
|
// Normal workday (excluding vacation days)
|
||||||
totalWorkdaysInMonth++;
|
totalWorkdaysInMonth++;
|
||||||
if (dateObj <= today) {
|
if (dateObj <= countUntil) {
|
||||||
workdaysPassed++;
|
workdaysPassed++;
|
||||||
}
|
}
|
||||||
} else if (isFlextime && isWeekendHoliday) {
|
} else if (isFlextime && isWeekendHoliday) {
|
||||||
// Flextime on weekend/holiday counts as additional workday
|
// Flextime on weekend/holiday counts as additional workday
|
||||||
totalWorkdaysInMonth++;
|
totalWorkdaysInMonth++;
|
||||||
if (new Date(dateISO) <= today) {
|
if (new Date(dateISO) <= countUntil) {
|
||||||
workdaysPassed++;
|
workdaysPassed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3037,7 +3031,7 @@ async function handleExportPDF() {
|
|||||||
|
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
const entryDate = new Date(entry.date);
|
const entryDate = new Date(entry.date);
|
||||||
if (entryDate <= today) {
|
if (entryDate <= countUntil) {
|
||||||
if (!entry.entryType || entry.entryType === 'work') {
|
if (!entry.entryType || entry.entryType === 'work') {
|
||||||
totalNetHours += entry.netHours;
|
totalNetHours += entry.netHours;
|
||||||
workEntriesCount++;
|
workEntriesCount++;
|
||||||
|
|||||||
@@ -3,49 +3,49 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Modal state
|
// Modal state
|
||||||
export let currentEditingId = null;
|
let currentEditingId = null;
|
||||||
export let datePicker = null;
|
let datePicker = null;
|
||||||
export let startTimePicker = null;
|
let startTimePicker = null;
|
||||||
export let endTimePicker = null;
|
let endTimePicker = null;
|
||||||
export let filterFromPicker = null;
|
let filterFromPicker = null;
|
||||||
export let filterToPicker = null;
|
let filterToPicker = null;
|
||||||
|
|
||||||
// Timer state
|
// Timer state
|
||||||
export let timerInterval = null;
|
let timerInterval = null;
|
||||||
export let timerStartTime = null;
|
let timerStartTime = null;
|
||||||
export let timerPausedDuration = 0; // Total paused time in seconds
|
let timerPausedDuration = 0; // Total paused time in seconds
|
||||||
export let isPaused = false;
|
let isPaused = false;
|
||||||
export let pauseTimeout = null;
|
let pauseTimeout = null;
|
||||||
export let currentEntryId = null; // ID of today's entry being timed
|
let currentEntryId = null; // ID of today's entry being timed
|
||||||
|
|
||||||
// Current month display state
|
// Current month display state
|
||||||
export let displayYear = new Date().getFullYear();
|
let displayYear = new Date().getFullYear();
|
||||||
export let displayMonth = new Date().getMonth(); // 0-11
|
let displayMonth = new Date().getMonth(); // 0-11
|
||||||
|
|
||||||
// Bulk edit state
|
// Bulk edit state
|
||||||
export let bulkEditMode = false;
|
let bulkEditMode = false;
|
||||||
export let selectedEntries = new Set();
|
let selectedEntries = new Set();
|
||||||
|
|
||||||
// Setters for state mutations
|
// Setters for state mutations
|
||||||
export function setCurrentEditingId(id) { currentEditingId = id; }
|
function setCurrentEditingId(id) { currentEditingId = id; }
|
||||||
export function setDatePicker(picker) { datePicker = picker; }
|
function setDatePicker(picker) { datePicker = picker; }
|
||||||
export function setStartTimePicker(picker) { startTimePicker = picker; }
|
function setStartTimePicker(picker) { startTimePicker = picker; }
|
||||||
export function setEndTimePicker(picker) { endTimePicker = picker; }
|
function setEndTimePicker(picker) { endTimePicker = picker; }
|
||||||
export function setFilterFromPicker(picker) { filterFromPicker = picker; }
|
function setFilterFromPicker(picker) { filterFromPicker = picker; }
|
||||||
export function setFilterToPicker(picker) { filterToPicker = picker; }
|
function setFilterToPicker(picker) { filterToPicker = picker; }
|
||||||
|
|
||||||
export function setTimerInterval(interval) { timerInterval = interval; }
|
function setTimerInterval(interval) { timerInterval = interval; }
|
||||||
export function setTimerStartTime(time) { timerStartTime = time; }
|
function setTimerStartTime(time) { timerStartTime = time; }
|
||||||
export function setTimerPausedDuration(duration) { timerPausedDuration = duration; }
|
function setTimerPausedDuration(duration) { timerPausedDuration = duration; }
|
||||||
export function setIsPaused(paused) { isPaused = paused; }
|
function setIsPaused(paused) { isPaused = paused; }
|
||||||
export function setPauseTimeout(timeout) { pauseTimeout = timeout; }
|
function setPauseTimeout(timeout) { pauseTimeout = timeout; }
|
||||||
export function setCurrentEntryId(id) { currentEntryId = id; }
|
function setCurrentEntryId(id) { currentEntryId = id; }
|
||||||
|
|
||||||
export function setDisplayYear(year) { displayYear = year; }
|
function setDisplayYear(year) { displayYear = year; }
|
||||||
export function setDisplayMonth(month) { displayMonth = month; }
|
function setDisplayMonth(month) { displayMonth = month; }
|
||||||
|
|
||||||
export function setBulkEditMode(mode) { bulkEditMode = mode; }
|
function setBulkEditMode(mode) { bulkEditMode = mode; }
|
||||||
export function clearSelectedEntries() { selectedEntries.clear(); }
|
function clearSelectedEntries() { selectedEntries.clear(); }
|
||||||
export function addSelectedEntry(id) { selectedEntries.add(id); }
|
function addSelectedEntry(id) { selectedEntries.add(id); }
|
||||||
export function removeSelectedEntry(id) { selectedEntries.delete(id); }
|
function removeSelectedEntry(id) { selectedEntries.delete(id); }
|
||||||
export function hasSelectedEntry(id) { return selectedEntries.has(id); }
|
function hasSelectedEntry(id) { return selectedEntries.has(id); }
|
||||||
|
|||||||
Reference in New Issue
Block a user