From 9762ede7ec602835ff828428cd89ceedf0b504a4 Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Sat, 6 Jun 2026 18:54:05 -0400 Subject: [PATCH] feat: show live estimated hours/earnings while timer is running Summary cards now include the in-progress session's hours and earnings, rounded up to the nearest 15-min increment (matching clock-out billing logic). A secondary "+Xh est." line appears below each stat when a timer is active, updating every second as the elapsed counter ticks. Co-Authored-By: Claude Sonnet 4.6 --- src/app/dashboard/time-clock/page.tsx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/time-clock/page.tsx b/src/app/dashboard/time-clock/page.tsx index e37e555..47117ba 100644 --- a/src/app/dashboard/time-clock/page.tsx +++ b/src/app/dashboard/time-clock/page.tsx @@ -209,6 +209,12 @@ export default function TimeClockPage() { const completedEntries = entries.filter((e) => e.endedAt !== null); + // Live estimate for running timer, rounded up to 15-min increments (no minimum while running) + const estimatedHours = running ? Math.ceil(elapsed / 900) * 0.25 : 0; + const estimatedEarnings = running ? estimatedHours * (running.rate ?? 0) : 0; + const displayHours = (summary?.totalHours ?? 0) + estimatedHours; + const displayEarnings = (summary?.totalEarnings ?? 0) + estimatedEarnings; + return (

- {formatDuration(summary?.totalHours)} + {formatDuration(displayHours || undefined)}

+ {running && estimatedHours > 0 && ( +

+ +{formatDuration(estimatedHours)} est. +

+ )} @@ -246,8 +257,13 @@ export default function TimeClockPage() { Earnings

- {formatCurrency(summary?.totalEarnings ?? 0)} + {formatCurrency(displayEarnings)}

+ {running && estimatedEarnings > 0 && ( +

+ +{formatCurrency(estimatedEarnings)} est. +

+ )}