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
All checks were successful
Build and Push Docker Image / build (push) Successful in 25s
This commit is contained in:
@@ -382,6 +382,23 @@
|
||||
Startzeit manuell eingeben
|
||||
</button>
|
||||
|
||||
<!-- Target hours selector -->
|
||||
<div class="mt-3 flex items-center gap-2">
|
||||
<label for="targetHoursSelect" class="text-sm text-gray-400">Soll-Stunden:</label>
|
||||
<select id="targetHoursSelect" class="px-3 py-1 bg-gray-700 text-gray-100 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm">
|
||||
<option value="1">1h</option>
|
||||
<option value="2">2h</option>
|
||||
<option value="3">3h</option>
|
||||
<option value="4">4h</option>
|
||||
<option value="5">5h</option>
|
||||
<option value="6">6h</option>
|
||||
<option value="7">7h</option>
|
||||
<option value="8" selected>8h</option>
|
||||
<option value="9">9h</option>
|
||||
<option value="10">10h</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<input type="text" id="manualStartTimeInput" class="hidden">
|
||||
|
||||
<!-- Additional Timer Metrics -->
|
||||
@@ -392,7 +409,7 @@
|
||||
</button>
|
||||
<div class="flex items-center gap-2 text-gray-300">
|
||||
<i data-lucide="target" class="w-4 h-4 text-green-400"></i>
|
||||
<span>Soll erreicht: <span id="targetReachedTime" class="font-semibold text-white">--:--</span> (8h)</span>
|
||||
<span>Soll erreicht: <span id="targetReachedTime" class="font-semibold text-white">--:--</span></span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-gray-300">
|
||||
<i data-lucide="timer" class="w-4 h-4 text-blue-400"></i>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -17,6 +17,7 @@ let timerPausedDuration = 0; // Total paused time in seconds
|
||||
let isPaused = false;
|
||||
let pauseTimeout = null;
|
||||
let currentEntryId = null; // ID of today's entry being timed
|
||||
let targetHours = 8; // Target work hours per day (1-10)
|
||||
|
||||
// Current month display state
|
||||
let displayYear = new Date().getFullYear();
|
||||
|
||||
Reference in New Issue
Block a user