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) {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate();
|
||||
|
||||
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 => {
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
// Timer state
|
||||
let timerInterval = null;
|
||||
let timerStartTime = null;
|
||||
let timerPausedDuration = 0; // Total paused time in seconds
|
||||
let isPaused = false;
|
||||
let pauseTimeout = null;
|
||||
// Additional timer state (beyond state.js)
|
||||
let pauseStartElapsed = 0; // Elapsed time when pause started (to freeze display)
|
||||
let pauseEndTime = 0; // Timestamp when pause will end (for countdown)
|
||||
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
|
||||
let currentView = 'monthly'; // 'monthly' or 'filter'
|
||||
let currentFilterFrom = null;
|
||||
let currentFilterTo = null;
|
||||
|
||||
// Bulk edit state
|
||||
let bulkEditMode = false;
|
||||
let selectedEntries = new Set();
|
||||
|
||||
// Settings state
|
||||
let currentBundesland = 'BW'; // Default: Baden-Württemberg
|
||||
let totalVacationDays = 30; // Default vacation days per year
|
||||
@@ -2109,7 +2089,10 @@ async function bulkExportPDF() {
|
||||
|
||||
// Count workdays based on selected entries only
|
||||
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 isFlextime = flextimeDaysSet.has(dateISO);
|
||||
const isWeekendHoliday = isWeekendOrHoliday(dateObj);
|
||||
@@ -2975,8 +2958,19 @@ async function handleExportPDF() {
|
||||
|
||||
// Calculate statistics
|
||||
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 totalWorkdaysInMonth = 0;
|
||||
|
||||
@@ -3008,13 +3002,13 @@ async function handleExportPDF() {
|
||||
if (!isWeekendHoliday && !isVacation) {
|
||||
// Normal workday (excluding vacation days)
|
||||
totalWorkdaysInMonth++;
|
||||
if (dateObj <= today) {
|
||||
if (dateObj <= countUntil) {
|
||||
workdaysPassed++;
|
||||
}
|
||||
} else if (isFlextime && isWeekendHoliday) {
|
||||
// Flextime on weekend/holiday counts as additional workday
|
||||
totalWorkdaysInMonth++;
|
||||
if (new Date(dateISO) <= today) {
|
||||
if (new Date(dateISO) <= countUntil) {
|
||||
workdaysPassed++;
|
||||
}
|
||||
}
|
||||
@@ -3037,7 +3031,7 @@ async function handleExportPDF() {
|
||||
|
||||
entries.forEach(entry => {
|
||||
const entryDate = new Date(entry.date);
|
||||
if (entryDate <= today) {
|
||||
if (entryDate <= countUntil) {
|
||||
if (!entry.entryType || entry.entryType === 'work') {
|
||||
totalNetHours += entry.netHours;
|
||||
workEntriesCount++;
|
||||
|
||||
@@ -3,49 +3,49 @@
|
||||
*/
|
||||
|
||||
// Modal state
|
||||
export let currentEditingId = null;
|
||||
export let datePicker = null;
|
||||
export let startTimePicker = null;
|
||||
export let endTimePicker = null;
|
||||
export let filterFromPicker = null;
|
||||
export let filterToPicker = null;
|
||||
let currentEditingId = null;
|
||||
let datePicker = null;
|
||||
let startTimePicker = null;
|
||||
let endTimePicker = null;
|
||||
let filterFromPicker = null;
|
||||
let filterToPicker = null;
|
||||
|
||||
// Timer state
|
||||
export let timerInterval = null;
|
||||
export let timerStartTime = null;
|
||||
export let timerPausedDuration = 0; // Total paused time in seconds
|
||||
export let isPaused = false;
|
||||
export let pauseTimeout = null;
|
||||
export let currentEntryId = null; // ID of today's entry being timed
|
||||
let timerInterval = null;
|
||||
let timerStartTime = null;
|
||||
let timerPausedDuration = 0; // Total paused time in seconds
|
||||
let isPaused = false;
|
||||
let pauseTimeout = null;
|
||||
let currentEntryId = null; // ID of today's entry being timed
|
||||
|
||||
// Current month display state
|
||||
export let displayYear = new Date().getFullYear();
|
||||
export let displayMonth = new Date().getMonth(); // 0-11
|
||||
let displayYear = new Date().getFullYear();
|
||||
let displayMonth = new Date().getMonth(); // 0-11
|
||||
|
||||
// Bulk edit state
|
||||
export let bulkEditMode = false;
|
||||
export let selectedEntries = new Set();
|
||||
let bulkEditMode = false;
|
||||
let selectedEntries = new Set();
|
||||
|
||||
// Setters for state mutations
|
||||
export function setCurrentEditingId(id) { currentEditingId = id; }
|
||||
export function setDatePicker(picker) { datePicker = picker; }
|
||||
export function setStartTimePicker(picker) { startTimePicker = picker; }
|
||||
export function setEndTimePicker(picker) { endTimePicker = picker; }
|
||||
export function setFilterFromPicker(picker) { filterFromPicker = picker; }
|
||||
export function setFilterToPicker(picker) { filterToPicker = picker; }
|
||||
function setCurrentEditingId(id) { currentEditingId = id; }
|
||||
function setDatePicker(picker) { datePicker = picker; }
|
||||
function setStartTimePicker(picker) { startTimePicker = picker; }
|
||||
function setEndTimePicker(picker) { endTimePicker = picker; }
|
||||
function setFilterFromPicker(picker) { filterFromPicker = picker; }
|
||||
function setFilterToPicker(picker) { filterToPicker = picker; }
|
||||
|
||||
export function setTimerInterval(interval) { timerInterval = interval; }
|
||||
export function setTimerStartTime(time) { timerStartTime = time; }
|
||||
export function setTimerPausedDuration(duration) { timerPausedDuration = duration; }
|
||||
export function setIsPaused(paused) { isPaused = paused; }
|
||||
export function setPauseTimeout(timeout) { pauseTimeout = timeout; }
|
||||
export function setCurrentEntryId(id) { currentEntryId = id; }
|
||||
function setTimerInterval(interval) { timerInterval = interval; }
|
||||
function setTimerStartTime(time) { timerStartTime = time; }
|
||||
function setTimerPausedDuration(duration) { timerPausedDuration = duration; }
|
||||
function setIsPaused(paused) { isPaused = paused; }
|
||||
function setPauseTimeout(timeout) { pauseTimeout = timeout; }
|
||||
function setCurrentEntryId(id) { currentEntryId = id; }
|
||||
|
||||
export function setDisplayYear(year) { displayYear = year; }
|
||||
export function setDisplayMonth(month) { displayMonth = month; }
|
||||
function setDisplayYear(year) { displayYear = year; }
|
||||
function setDisplayMonth(month) { displayMonth = month; }
|
||||
|
||||
export function setBulkEditMode(mode) { bulkEditMode = mode; }
|
||||
export function clearSelectedEntries() { selectedEntries.clear(); }
|
||||
export function addSelectedEntry(id) { selectedEntries.add(id); }
|
||||
export function removeSelectedEntry(id) { selectedEntries.delete(id); }
|
||||
export function hasSelectedEntry(id) { return selectedEntries.has(id); }
|
||||
function setBulkEditMode(mode) { bulkEditMode = mode; }
|
||||
function clearSelectedEntries() { selectedEntries.clear(); }
|
||||
function addSelectedEntry(id) { selectedEntries.add(id); }
|
||||
function removeSelectedEntry(id) { selectedEntries.delete(id); }
|
||||
function hasSelectedEntry(id) { return selectedEntries.has(id); }
|
||||
|
||||
Reference in New Issue
Block a user