From 6ebdd788552e3b5a2c000fe49d407f8c8a138090 Mon Sep 17 00:00:00 2001 From: chamiakJ Date: Thu, 10 Jul 2025 12:27:15 +0530 Subject: [PATCH] feat(task-timer): add timer start and stop handlers for task management - Implemented handleTimerStart and handleTimerStop functions to manage task timer state via socket events. - Updated useTaskSocketHandlers to register new socket event listeners for timer actions. - Enhanced useTaskTimer to retrieve active timer state from both the old and new task management slices. - Added activeTimer property to Task type for tracking the start timestamp of active timers. --- .../src/hooks/useTaskSocketHandlers.ts | 54 +++++++++++++++++++ worklenz-frontend/src/hooks/useTaskTimer.ts | 6 ++- .../src/types/task-management.types.ts | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts b/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts index c00fa14d..7cf88cfc 100644 --- a/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts +++ b/worklenz-frontend/src/hooks/useTaskSocketHandlers.ts @@ -930,6 +930,56 @@ export const useTaskSocketHandlers = () => { // console.log('🔄 Task assignees change (limited data):', data); }, []); + // Handler for timer start events + const handleTimerStart = useCallback((data: string) => { + try { + const { task_id, start_time } = typeof data === 'string' ? JSON.parse(data) : data; + if (!task_id) return; + + // Update the task-management slice to include timer state + const currentTask = store.getState().taskManagement.entities[task_id]; + if (currentTask) { + const updatedTask: Task = { + ...currentTask, + timeTracking: { + ...currentTask.timeTracking, + activeTimer: start_time ? (typeof start_time === 'number' ? start_time : parseInt(start_time)) : Date.now(), + }, + updatedAt: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + dispatch(updateTask(updatedTask)); + } + } catch (error) { + logger.error('Error handling timer start event:', error); + } + }, [dispatch]); + + // Handler for timer stop events + const handleTimerStop = useCallback((data: string) => { + try { + const { task_id } = typeof data === 'string' ? JSON.parse(data) : data; + if (!task_id) return; + + // Update the task-management slice to remove timer state + const currentTask = store.getState().taskManagement.entities[task_id]; + if (currentTask) { + const updatedTask: Task = { + ...currentTask, + timeTracking: { + ...currentTask.timeTracking, + activeTimer: undefined, + }, + updatedAt: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + dispatch(updateTask(updatedTask)); + } + } catch (error) { + logger.error('Error handling timer stop event:', error); + } + }, [dispatch]); + // Register socket event listeners useEffect(() => { if (!socket) return; @@ -961,6 +1011,8 @@ export const useTaskSocketHandlers = () => { { event: SocketEvents.QUICK_TASK.toString(), handler: handleNewTaskReceived }, { event: SocketEvents.TASK_PROGRESS_UPDATED.toString(), handler: handleTaskProgressUpdated }, { event: SocketEvents.TASK_CUSTOM_COLUMN_UPDATE.toString(), handler: handleCustomColumnUpdate }, + { event: SocketEvents.TASK_TIMER_START.toString(), handler: handleTimerStart }, + { event: SocketEvents.TASK_TIMER_STOP.toString(), handler: handleTimerStop }, ]; @@ -993,6 +1045,8 @@ export const useTaskSocketHandlers = () => { handleNewTaskReceived, handleTaskProgressUpdated, handleCustomColumnUpdate, + handleTimerStart, + handleTimerStop, ]); }; diff --git a/worklenz-frontend/src/hooks/useTaskTimer.ts b/worklenz-frontend/src/hooks/useTaskTimer.ts index cdb89ba1..0e7f7885 100644 --- a/worklenz-frontend/src/hooks/useTaskTimer.ts +++ b/worklenz-frontend/src/hooks/useTaskTimer.ts @@ -6,6 +6,7 @@ import logger from '@/utils/errorLogger'; import { useAppDispatch } from '@/hooks/useAppDispatch'; import { updateTaskTimeTracking } from '@/features/tasks/tasks.slice'; import { useAppSelector } from '@/hooks/useAppSelector'; +import { selectTaskById } from '@/features/task-management/task-management.slice'; export const useTaskTimer = (taskId: string, initialStartTime: number | null) => { const dispatch = useAppDispatch(); @@ -15,7 +16,10 @@ export const useTaskTimer = (taskId: string, initialStartTime: number | null) => const hasInitialized = useRef(false); // Track if we've initialized const activeTimers = useAppSelector(state => state.taskReducer.activeTimers); - const reduxStartTime = activeTimers[taskId]; + const task = useAppSelector(state => selectTaskById(state, taskId)); + + // Check both the old slice (activeTimers) and new slice (task.timeTracking.activeTimer) + const reduxStartTime = activeTimers[taskId] || task?.timeTracking?.activeTimer; const started = Boolean(reduxStartTime); const [timeString, setTimeString] = useState(DEFAULT_TIME_LEFT); diff --git a/worklenz-frontend/src/types/task-management.types.ts b/worklenz-frontend/src/types/task-management.types.ts index cb0e749d..87847125 100644 --- a/worklenz-frontend/src/types/task-management.types.ts +++ b/worklenz-frontend/src/types/task-management.types.ts @@ -45,6 +45,7 @@ export interface Task { timeTracking?: { // Time tracking information logged?: number; estimated?: number; + activeTimer?: number; // Active timer start timestamp }; custom_column_values?: Record; // Custom column values isTemporary?: boolean; // Temporary task indicator