feat: update better-sqlite3 dependency and enhance timer metrics with target hours functionality
Some checks failed
Build and Push Docker Image / build (push) Failing after 27s
Some checks failed
Build and Push Docker Image / build (push) Failing after 27s
This commit is contained in:
@@ -226,6 +226,9 @@ async function startWork() {
|
||||
timerPausedDuration = 0;
|
||||
isPaused = false;
|
||||
|
||||
// Save current target hours
|
||||
await setSetting('targetHours', targetHours);
|
||||
|
||||
// Update UI
|
||||
const startBtn = document.getElementById('btnStartWork');
|
||||
const stopBtn = document.getElementById('btnStopWork');
|
||||
@@ -278,6 +281,11 @@ async function stopWork() {
|
||||
timerPausedDuration = 0;
|
||||
isPaused = false;
|
||||
|
||||
// Reset target hours to 8 and clear saved setting
|
||||
targetHours = 8;
|
||||
document.getElementById('targetHoursSelect').value = 8;
|
||||
await setSetting('targetHours', null);
|
||||
|
||||
// Update UI
|
||||
const startBtn = document.getElementById('btnStartWork');
|
||||
const stopBtn = document.getElementById('btnStopWork');
|
||||
@@ -339,7 +347,8 @@ function updateTimer() {
|
||||
const balanceCell = document.getElementById('current-day-balance');
|
||||
if (balanceCell) {
|
||||
const netHours = elapsed / 3600; // Convert seconds to hours
|
||||
const deviation = netHours - targetHours;
|
||||
// Always use 8h standard target for balance calculation (not the dropdown target)
|
||||
const deviation = netHours - 8.0;
|
||||
const baseBalance = parseFloat(balanceCell.dataset.baseBalance || 0);
|
||||
const currentBalance = baseBalance + deviation;
|
||||
|
||||
@@ -383,6 +392,7 @@ function updateTimer() {
|
||||
function updateTimerMetrics(netElapsedSeconds) {
|
||||
const targetReachedTimeSpan = document.getElementById('targetReachedTime');
|
||||
const timeUntilTargetSpan = document.getElementById('timeUntilTarget');
|
||||
const balanceAtTargetSpan = document.getElementById('balanceAtTarget');
|
||||
|
||||
if (!timerStartTime) {
|
||||
return;
|
||||
@@ -424,6 +434,23 @@ function updateTimerMetrics(netElapsedSeconds) {
|
||||
timeUntilTargetSpan.classList.remove('text-green-400');
|
||||
}
|
||||
|
||||
// Calculate balance when target is reached
|
||||
// Get base balance from current day row (balance before today)
|
||||
const balanceCell = document.getElementById('current-day-balance');
|
||||
if (balanceCell && balanceAtTargetSpan) {
|
||||
const baseBalance = parseFloat(balanceCell.dataset.baseBalance || 0);
|
||||
// Deviation when target hours are reached: targetHours - 8h (standard)
|
||||
const targetNetHours = targetHours;
|
||||
const deviation = targetNetHours - 8.0;
|
||||
const balanceAtTarget = baseBalance + deviation;
|
||||
|
||||
const balanceColor = balanceAtTarget >= 0 ? 'text-green-400' : 'text-red-400';
|
||||
const balanceSign = balanceAtTarget >= 0 ? '+' : '';
|
||||
|
||||
balanceAtTargetSpan.className = `font-semibold ${balanceColor}`;
|
||||
balanceAtTargetSpan.textContent = `${balanceSign}${balanceAtTarget.toFixed(2)}h`;
|
||||
}
|
||||
|
||||
// Reinitialize Lucide icons for the new metrics
|
||||
if (typeof lucide !== 'undefined' && lucide.createIcons) {
|
||||
lucide.createIcons();
|
||||
@@ -1055,20 +1082,25 @@ async function loadMonthlyView() {
|
||||
updateStatistics(entries);
|
||||
updateBridgeDaysDisplay();
|
||||
|
||||
// Show/hide PDF export button based on whether month is complete
|
||||
const today = new Date();
|
||||
const isCurrentOrFutureMonth = displayYear > today.getFullYear() ||
|
||||
(displayYear === today.getFullYear() && displayMonth >= today.getMonth());
|
||||
|
||||
// Show/hide PDF export button based on whether last day has complete times
|
||||
const pdfButton = document.getElementById('btnExportPDF');
|
||||
const pdfButtonMobile = document.getElementById('btnExportPDFMobile');
|
||||
|
||||
if (isCurrentOrFutureMonth) {
|
||||
pdfButton.style.display = 'none';
|
||||
if (pdfButtonMobile) pdfButtonMobile.style.display = 'none';
|
||||
} else {
|
||||
// Check if last day of month has start and end time (and they're different)
|
||||
const lastDayDate = `${displayYear}-${String(displayMonth + 1).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
|
||||
const lastDayEntry = entries.find(e => e.date === lastDayDate);
|
||||
|
||||
const isLastDayComplete = lastDayEntry &&
|
||||
lastDayEntry.startTime &&
|
||||
lastDayEntry.endTime &&
|
||||
lastDayEntry.startTime !== lastDayEntry.endTime;
|
||||
|
||||
if (isLastDayComplete) {
|
||||
pdfButton.style.display = '';
|
||||
if (pdfButtonMobile) pdfButtonMobile.style.display = '';
|
||||
} else {
|
||||
pdfButton.style.display = 'none';
|
||||
if (pdfButtonMobile) pdfButtonMobile.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2804,6 +2836,13 @@ async function loadSettings() {
|
||||
document.getElementById('companyHolidayNewYear').checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load target hours (always restore dropdown value)
|
||||
const savedTargetHours = await getSetting('targetHours');
|
||||
if (savedTargetHours) {
|
||||
targetHours = parseInt(savedTargetHours);
|
||||
document.getElementById('targetHoursSelect').value = targetHours;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3706,6 +3745,9 @@ async function handleManualStartTime(timeStr) {
|
||||
timerPausedDuration = 0;
|
||||
isPaused = false;
|
||||
|
||||
// Save current target hours
|
||||
await setSetting('targetHours', targetHours);
|
||||
|
||||
// Update UI
|
||||
const startBtn = document.getElementById('btnStartWork');
|
||||
const stopBtn = document.getElementById('btnStopWork');
|
||||
@@ -3846,10 +3888,12 @@ function initializeEventListeners() {
|
||||
document.getElementById('btnStopWork').addEventListener('click', stopWork);
|
||||
|
||||
// Target hours selector
|
||||
document.getElementById('targetHoursSelect').addEventListener('change', (e) => {
|
||||
document.getElementById('targetHoursSelect').addEventListener('change', async (e) => {
|
||||
targetHours = parseInt(e.target.value);
|
||||
// Update metrics if timer is running
|
||||
|
||||
// Save target hours if timer is running
|
||||
if (timerStartTime) {
|
||||
await setSetting('targetHours', targetHours);
|
||||
const elapsed = Math.floor((Date.now() - timerStartTime) / 1000) - timerPausedDuration;
|
||||
updateTimerMetrics(elapsed);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user