import { useEffect, useRef } from 'react'; import { Task } from '@shared/schema'; interface UseTimerProps { tasks: Task[]; onTaskUpdate: (taskId: string, updates: Partial) => void; } export function useTimer({ tasks, onTaskUpdate }: UseTimerProps) { const intervalRef = useRef(null); const lastUpdateRef = useRef<{ [taskId: string]: number }>({}); useEffect(() => { // Find tasks that are currently being tracked const trackingTasks = tasks.filter(task => task.isTracking); if (trackingTasks.length > 0) { // Start the timer intervalRef.current = setInterval(() => { const now = Date.now(); trackingTasks.forEach(task => { // Initialize last update time if not set if (!lastUpdateRef.current[task.id]) { lastUpdateRef.current[task.id] = now; return; } // Calculate elapsed time since last update (in minutes) const elapsed = (now - lastUpdateRef.current[task.id]) / 1000 / 60; // Only update if at least 1 minute has passed (to avoid too frequent updates) if (elapsed >= 1) { const currentTime = task.timeTracked || 0; const newTime = currentTime + Math.floor(elapsed); onTaskUpdate(task.id, { timeTracked: newTime }); lastUpdateRef.current[task.id] = now; console.log(`Timer updated for "${task.title}": +${Math.floor(elapsed)}min (total: ${newTime}min)`); } }); }, 60000); // Update every minute } else { // No tasks are being tracked, clear the timer if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } // Clear last update times for stopped tasks lastUpdateRef.current = {}; } // Cleanup on unmount or when tracking tasks change return () => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } }; }, [tasks.map(t => `${t.id}:${t.isTracking}`).join(','), onTaskUpdate]); // Initialize last update times for currently tracking tasks useEffect(() => { const now = Date.now(); tasks.forEach(task => { if (task.isTracking && !lastUpdateRef.current[task.id]) { lastUpdateRef.current[task.id] = now; } else if (!task.isTracking && lastUpdateRef.current[task.id]) { delete lastUpdateRef.current[task.id]; } }); }, [tasks]); const startTimer = (taskId: string) => { const now = Date.now(); lastUpdateRef.current[taskId] = now; onTaskUpdate(taskId, { isTracking: true }); console.log(`Timer started for task: ${taskId}`); }; const stopTimer = (taskId: string) => { const task = tasks.find(t => t.id === taskId); if (task && lastUpdateRef.current[taskId]) { const now = Date.now(); const elapsed = (now - lastUpdateRef.current[taskId]) / 1000 / 60; if (elapsed >= 0.1) { // Add time if at least 6 seconds have passed const currentTime = task.timeTracked || 0; const additionalTime = Math.max(1, Math.round(elapsed)); // At least 1 minute const newTime = currentTime + additionalTime; onTaskUpdate(taskId, { isTracking: false, timeTracked: newTime }); console.log(`Timer stopped for "${task.title}": +${additionalTime}min (total: ${newTime}min)`); } else { onTaskUpdate(taskId, { isTracking: false }); } delete lastUpdateRef.current[taskId]; } else { onTaskUpdate(taskId, { isTracking: false }); } }; return { startTimer, stopTimer }; }