feat(timer): enhance timer conflict resolution and state management

- Updated `useTaskTimerWithConflictCheck` to immediately update Redux state when stopping a conflicting timer, ensuring synchronization between task management and time tracking slices.
- Adjusted the timer start logic to trigger immediately after state updates, improving user experience during timer transitions.
- Added necessary imports for Redux dispatch and state management to support the new functionality.
This commit is contained in:
chamikaJ
2025-07-30 13:27:41 +05:30
parent d9700a9b2c
commit f085f87107

View File

@@ -5,6 +5,10 @@ import { useSocket } from '@/socket/socketContext';
import { SocketEvents } from '@/shared/socket-events'; import { SocketEvents } from '@/shared/socket-events';
import { taskTimeLogsApiService } from '@/api/tasks/task-time-logs.api.service'; import { taskTimeLogsApiService } from '@/api/tasks/task-time-logs.api.service';
import { useTaskTimer } from './useTaskTimer'; import { useTaskTimer } from './useTaskTimer';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { updateTask } from '@/features/task-management/task-management.slice';
import { updateTaskTimeTracking } from '@/features/tasks/tasks.slice';
import { store } from '@/app/store';
interface ConflictingTimer { interface ConflictingTimer {
task_id: string; task_id: string;
@@ -13,6 +17,7 @@ interface ConflictingTimer {
} }
export const useTaskTimerWithConflictCheck = (taskId: string, timerStartTime: string | null) => { export const useTaskTimerWithConflictCheck = (taskId: string, timerStartTime: string | null) => {
const dispatch = useAppDispatch();
const { socket } = useSocket(); const { socket } = useSocket();
const { t: tTable } = useTranslation('task-list-table'); const { t: tTable } = useTranslation('task-list-table');
const { t: tCommon } = useTranslation('common'); const { t: tCommon } = useTranslation('common');
@@ -60,17 +65,35 @@ export const useTaskTimerWithConflictCheck = (taskId: string, timerStartTime: st
okText: tTable('timer.stopAndStart'), okText: tTable('timer.stopAndStart'),
cancelText: tCommon('cancel'), cancelText: tCommon('cancel'),
onOk: () => { onOk: () => {
// Stop the conflicting timer // Stop the conflicting timer and immediately update Redux state
if (socket) { if (socket) {
socket.emit(SocketEvents.TASK_TIMER_STOP.toString(), JSON.stringify({ socket.emit(SocketEvents.TASK_TIMER_STOP.toString(), JSON.stringify({
task_id: conflictingTimer.task_id task_id: conflictingTimer.task_id
})); }));
// Immediately update Redux state for the stopped timer
const conflictingTask = store.getState().taskManagement.entities[conflictingTimer.task_id];
if (conflictingTask) {
const updatedTask = {
...conflictingTask,
timeTracking: {
...conflictingTask.timeTracking,
activeTimer: undefined,
},
updatedAt: new Date().toISOString(),
updated_at: new Date().toISOString(),
};
dispatch(updateTask(updatedTask));
}
// Also update the tasks slice activeTimers to keep both slices in sync
dispatch(updateTaskTimeTracking({ taskId: conflictingTimer.task_id, timeTracking: null }));
} }
// Start the new timer after a short delay // Start the new timer immediately after updating state
setTimeout(() => { setTimeout(() => {
originalHook.handleStartTimer(); originalHook.handleStartTimer();
}, 100); }, 50);
}, },
}); });
} else { } else {
@@ -84,7 +107,7 @@ export const useTaskTimerWithConflictCheck = (taskId: string, timerStartTime: st
} finally { } finally {
setIsCheckingConflict(false); setIsCheckingConflict(false);
} }
}, [isCheckingConflict, checkForConflictingTimers, tTable, tCommon, socket, originalHook]); }, [isCheckingConflict, checkForConflictingTimers, tTable, tCommon, socket, originalHook, dispatch]);
return { return {
...originalHook, ...originalHook,