import { differenceInSeconds, parseISO } from 'date-fns' import { Clock, Play, Square } from 'lucide-react' import { useEffect, useMemo, useState } from 'react' import { taskService } from '../services/taskService' import { cn } from '../lib/utils' import type { TaskResponse } from '../types/task' interface TaskTimerProps { task: TaskResponse onUpdate: () => void } function formatDuration(seconds: number) { const hrs = Math.floor(seconds / 3600) const mins = Math.floor((seconds % 3600) / 60) const secs = seconds % 60 return [ hrs > 0 ? String(hrs).padStart(2, '0') : '00', String(mins).padStart(2, '0'), String(secs).padStart(2, '0'), ].join(':') } export function TaskTimer({ task, onUpdate }: TaskTimerProps) { const [isActionLoading, setIsActionLoading] = useState(false) const history = task.history ?? [] const runningItem = useMemo( () => history.find((item) => !item.endAt), [history], ) const accumulatedSeconds = useMemo(() => { return history.reduce((acc, item) => { if (item.endAt) { return acc + differenceInSeconds(parseISO(item.endAt), parseISO(item.startAt)) } return acc }, 0) }, [history]) const [displaySeconds, setDisplaySeconds] = useState(0) useEffect(() => { let interval: ReturnType | null = null if (runningItem) { interval = setInterval(() => { const runningSeconds = differenceInSeconds(new Date(), parseISO(runningItem.startAt)) setDisplaySeconds(accumulatedSeconds + runningSeconds) }, 1000) } else { setDisplaySeconds(accumulatedSeconds) } return () => { if (interval) clearInterval(interval) } }, [runningItem, accumulatedSeconds]) // Initial calculation useEffect(() => { if (runningItem) { const runningSeconds = differenceInSeconds(new Date(), parseISO(runningItem.startAt)) setDisplaySeconds(accumulatedSeconds + runningSeconds) } else { setDisplaySeconds(accumulatedSeconds) } }, [runningItem, accumulatedSeconds]) async function handleStart(e: React.MouseEvent) { e.stopPropagation() setIsActionLoading(true) try { await taskService.startTask(task.id) onUpdate() } catch (error) { console.error('Failed to start task', error) } finally { setIsActionLoading(false) } } async function handleStop(e: React.MouseEvent) { e.stopPropagation() setIsActionLoading(true) try { await taskService.stopTask(task.id) onUpdate() } catch (error) { console.error('Failed to stop task', error) } finally { setIsActionLoading(false) } } return (
{/* Active Indicator Pulse */} {runningItem && (
)}
{runningItem ? 'Contagem Ativa' : 'Tempo Total'} {formatDuration(displaySeconds)}
{runningItem ? ( ) : ( )}
) }