feat: add target hours selector and update timer calculations based on user input
All checks were successful
Build and Push Docker Image / build (push) Successful in 25s

This commit is contained in:
Felix Schlusche
2025-10-30 17:18:38 +01:00
parent 17906c76f2
commit 763d7d141b
3 changed files with 43 additions and 10 deletions

View File

@@ -339,7 +339,7 @@ function updateTimer() {
const balanceCell = document.getElementById('current-day-balance');
if (balanceCell) {
const netHours = elapsed / 3600; // Convert seconds to hours
const deviation = netHours - 8.0;
const deviation = netHours - targetHours;
const baseBalance = parseFloat(balanceCell.dataset.baseBalance || 0);
const currentBalance = baseBalance + deviation;
@@ -388,8 +388,8 @@ function updateTimerMetrics(netElapsedSeconds) {
return;
}
// Target: 8 hours (28800 seconds)
const targetSeconds = 8 * 60 * 60;
// Target hours from user selection (default 8)
const targetSeconds = targetHours * 60 * 60;
// Calculate total pause time: 30 min after 6h + 15 min after 9h
const pauseDuration30Min = 30 * 60; // 30 minutes in seconds
@@ -398,14 +398,14 @@ function updateTimerMetrics(netElapsedSeconds) {
// Time needed including pauses
// After 6h work -> 30 min pause
// After 9h work -> 15 min pause
// Total gross time = 8h work + 30min pause + 15min pause = 8h 45min
// Total gross time = target work hours + 30min pause + 15min pause
const totalGrossTimeNeeded = targetSeconds + pauseDuration30Min + pauseDuration15Min;
// Calculate when target will be reached (clock time)
const targetReachedTimestamp = new Date(timerStartTime + totalGrossTimeNeeded * 1000);
const targetHours = String(targetReachedTimestamp.getHours()).padStart(2, '0');
const targetMinutes = String(targetReachedTimestamp.getMinutes()).padStart(2, '0');
targetReachedTimeSpan.textContent = `${targetHours}:${targetMinutes}`;
const targetHoursTime = String(targetReachedTimestamp.getHours()).padStart(2, '0');
const targetMinutesDisplay = String(targetReachedTimestamp.getMinutes()).padStart(2, '0');
targetReachedTimeSpan.textContent = `${targetHoursTime}:${targetMinutesDisplay}`;
// Calculate countdown to target (remaining net work time)
const remainingNetSeconds = Math.max(0, targetSeconds - netElapsedSeconds);
@@ -823,16 +823,21 @@ function renderMonthlyView(entries) {
let balanceCell = '';
if (isPastDay && entryType !== 'vacation') {
// For all workdays (including flextime): Actual - Target (8h)
// For all workdays (including flextime): Actual - Target (8h default)
// Flextime has netHours = 0, so deviation will be -8h
// For current day: store balance before today, then use custom target hours in live update
const balanceBeforeToday = runningBalance;
const deviation = entry.netHours - 8.0;
runningBalance += deviation;
const balanceColor = runningBalance >= 0 ? 'text-green-400' : 'text-red-400';
const balanceSign = runningBalance >= 0 ? '+' : '';
// Add ID for current day to enable live updates
// Store balance before today, so live update can add current day's deviation with custom target
const balanceId = isToday && entryType === 'work' ? 'id="current-day-balance"' : '';
const balanceDataAttr = isToday && entryType === 'work' ? `data-base-balance="${runningBalance - deviation}"` : '';
const balanceDataAttr = isToday && entryType === 'work' ? `data-base-balance="${balanceBeforeToday}"` : '';
balanceCell = `<td class="px-4 py-3 whitespace-nowrap text-sm font-semibold ${balanceColor}" ${balanceId} ${balanceDataAttr}>${balanceSign}${runningBalance.toFixed(2)}h</td>`;
} else {
@@ -3840,6 +3845,16 @@ function initializeEventListeners() {
document.getElementById('btnStartWork').addEventListener('click', startWork);
document.getElementById('btnStopWork').addEventListener('click', stopWork);
// Target hours selector
document.getElementById('targetHoursSelect').addEventListener('change', (e) => {
targetHours = parseInt(e.target.value);
// Update metrics if timer is running
if (timerStartTime) {
const elapsed = Math.floor((Date.now() - timerStartTime) / 1000) - timerPausedDuration;
updateTimerMetrics(elapsed);
}
});
// Timer status - manual start time entry
document.getElementById('timerStatus').addEventListener('click', () => {
if (!timerStartTime) {