feat(timer): add useTimerInitialization hook for managing running timers

- Introduced a new custom hook, useTimerInitialization, to fetch and initialize running timers from the backend when the project view loads.
- Integrated the hook into the ProjectView component to update Redux state with active timers and their corresponding task details.
- Enhanced error handling and logging for timer initialization to improve debugging and user experience.
This commit is contained in:
chamikaJ
2025-07-15 15:57:01 +05:30
parent 0434bbb73b
commit cb5610d99b
2 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import { useEffect, useRef } from 'react';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { updateTaskTimeTracking } from '@/features/tasks/tasks.slice';
import { updateTask } from '@/features/task-management/task-management.slice';
import { taskTimeLogsApiService } from '@/api/tasks/task-time-logs.api.service';
import { store } from '@/app/store';
import { Task } from '@/types/task-management.types';
import logger from '@/utils/errorLogger';
import moment from 'moment';
export const useTimerInitialization = () => {
const dispatch = useAppDispatch();
const hasInitialized = useRef(false);
useEffect(() => {
const initializeTimers = async () => {
// Prevent duplicate initialization
if (hasInitialized.current) {
return;
}
try {
hasInitialized.current = true;
// Fetch running timers from backend
const response = await taskTimeLogsApiService.getRunningTimers();
if (response && response.done && Array.isArray(response.body)) {
const runningTimers = response.body;
// Update Redux state for each running timer
runningTimers.forEach(timer => {
if (timer.task_id && timer.start_time) {
try {
// Convert start_time to timestamp
const startTime = moment(timer.start_time);
if (startTime.isValid()) {
const timestamp = startTime.valueOf();
// Update the tasks slice activeTimers
dispatch(updateTaskTimeTracking({
taskId: timer.task_id,
timeTracking: timestamp
}));
// Update the task-management slice if the task exists
const currentTask = store.getState().taskManagement.entities[timer.task_id];
if (currentTask) {
const updatedTask: Task = {
...currentTask,
timeTracking: {
...currentTask.timeTracking,
activeTimer: timestamp,
},
updatedAt: new Date().toISOString(),
updated_at: new Date().toISOString(),
};
dispatch(updateTask(updatedTask));
}
}
} catch (error) {
logger.error(`Error initializing timer for task ${timer.task_id}:`, error);
}
}
});
if (runningTimers.length > 0) {
logger.info(`Initialized ${runningTimers.length} running timers from backend`);
}
}
} catch (error) {
logger.error('Error initializing timers from backend:', error);
}
};
// Initialize timers when the hook mounts
initializeTimers();
}, [dispatch]);
};

View File

@@ -39,6 +39,7 @@ import { resetState as resetEnhancedKanbanState } from '@/features/enhanced-kanb
import { setProjectId as setInsightsProjectId } from '@/features/projects/insights/project-insights.slice';
import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
import { useTranslation } from 'react-i18next';
import { useTimerInitialization } from '@/hooks/useTimerInitialization';
// Import critical components synchronously to avoid suspense interruptions
@@ -89,6 +90,9 @@ const ProjectView = React.memo(() => {
const [taskid, setTaskId] = useState<string>(urlParams.taskId);
const [isInitialized, setIsInitialized] = useState(false);
// Initialize timer state from backend when project view loads
useTimerInitialization();
// Update local state when URL params change
useEffect(() => {
setActiveTab(urlParams.tab);