fix: sidebar In Session timer ticks every second and shows seconds
Timer now uses 1s interval (not 60s) and displays seconds when under a minute so it matches the session timer in the flow UI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,34 +9,37 @@ interface SidebarStatsBarProps {
|
|||||||
activeSessionStartTimes: string[]
|
activeSessionStartTimes: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDuration(minutes: number): string {
|
function formatDuration(totalSeconds: number): string {
|
||||||
if (minutes < 60) return `${minutes}m`
|
if (totalSeconds < 60) return `${totalSeconds}s`
|
||||||
const h = Math.floor(minutes / 60)
|
const totalMinutes = Math.floor(totalSeconds / 60)
|
||||||
const m = minutes % 60
|
if (totalMinutes < 60) return `${totalMinutes}m`
|
||||||
|
const h = Math.floor(totalMinutes / 60)
|
||||||
|
const m = totalMinutes % 60
|
||||||
return m > 0 ? `${h}h ${m}m` : `${h}h`
|
return m > 0 ? `${h}h ${m}m` : `${h}h`
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcActiveMinutes(startTimes: string[]): number {
|
function calcActiveSeconds(startTimes: string[]): number {
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
return startTimes.reduce((sum, st) => {
|
return startTimes.reduce((sum, st) => {
|
||||||
const elapsed = Math.floor((now - new Date(st).getTime()) / 60000)
|
const elapsed = Math.floor((now - new Date(st).getTime()) / 1000)
|
||||||
return sum + Math.max(0, elapsed)
|
return sum + Math.max(0, elapsed)
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SidebarStatsBar({ resolved, active, completedMinutes, activeSessionStartTimes }: SidebarStatsBarProps) {
|
export function SidebarStatsBar({ resolved, active, completedMinutes, activeSessionStartTimes }: SidebarStatsBarProps) {
|
||||||
const [liveMinutes, setLiveMinutes] = useState(() => calcActiveMinutes(activeSessionStartTimes))
|
const [liveSeconds, setLiveSeconds] = useState(() => calcActiveSeconds(activeSessionStartTimes))
|
||||||
|
|
||||||
// Tick every 60s to keep the timer live
|
// Tick every second to keep the timer in sync with the session timer
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLiveMinutes(calcActiveMinutes(activeSessionStartTimes))
|
setLiveSeconds(calcActiveSeconds(activeSessionStartTimes))
|
||||||
|
if (activeSessionStartTimes.length === 0) return
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
setLiveMinutes(calcActiveMinutes(activeSessionStartTimes))
|
setLiveSeconds(calcActiveSeconds(activeSessionStartTimes))
|
||||||
}, 60000)
|
}, 1000)
|
||||||
return () => clearInterval(interval)
|
return () => clearInterval(interval)
|
||||||
}, [activeSessionStartTimes])
|
}, [activeSessionStartTimes])
|
||||||
|
|
||||||
const totalMinutes = completedMinutes + liveMinutes
|
const totalSeconds = (completedMinutes * 60) + liveSeconds
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -71,9 +74,9 @@ export function SidebarStatsBar({ resolved, active, completedMinutes, activeSess
|
|||||||
<div className="flex-1 rounded-md bg-[rgba(255,255,255,0.02)] px-1 py-1.5 text-center">
|
<div className="flex-1 rounded-md bg-[rgba(255,255,255,0.02)] px-1 py-1.5 text-center">
|
||||||
<div
|
<div
|
||||||
className="font-label text-sm font-semibold leading-none text-muted-foreground"
|
className="font-label text-sm font-semibold leading-none text-muted-foreground"
|
||||||
aria-label={`${formatDuration(totalMinutes)} in session today`}
|
aria-label={`${formatDuration(totalSeconds)} in session today`}
|
||||||
>
|
>
|
||||||
{formatDuration(totalMinutes)}
|
{formatDuration(totalSeconds)}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 font-label text-[7px] uppercase tracking-[0.1em] text-[#3d4350]">
|
<div className="mt-1 font-label text-[7px] uppercase tracking-[0.1em] text-[#3d4350]">
|
||||||
In Session
|
In Session
|
||||||
|
|||||||
Reference in New Issue
Block a user