tududi/frontend/components/Task/TaskList.tsx
Chris 402d5b05e1
Fix Today page task completion issues (#970)
* Fix Today page task completion issues

- Fix completed task border color staying as priority color
  - Add isInCompletedSection prop to TaskItem for explicit completed state
  - Tasks in completed section now always show green border regardless of priority
  - Fixes race condition where status wasn't updated during optimistic UI update

- Fix completed task reappearing after unmarking and page refresh
  - Add defensive check in backend to force clear completed_at when status is not DONE
  - Add development logging in tasksService for debugging completion toggle
  - Ensures database state is consistent even if handleCompletionStatus doesn't clear it

- Update TaskList and TasksToday components to pass isInCompletedSection prop
  - Explicitly marks tasks rendered in the completed section
  - Prevents border color flickering during state transitions

* Add comprehensive logging to debug completion issues

* Fix duplicate API requests causing completion state issues

- Separate state update logic from API call in handleTaskUpdate
- Create new updateTaskInState function for state-only updates
- Pass onTaskCompletionToggle to completed section to avoid duplicate calls
- This fixes the persistence issue where unmarked tasks came back after refresh
- Completion toggles now only make ONE API call instead of two

* Add debug logging to updateTaskInState
2026-03-24 16:45:31 +02:00

72 lines
2.5 KiB
TypeScript

import React from 'react';
import TaskItem from './TaskItem';
import { Project } from '../../entities/Project';
import { Task } from '../../entities/Task';
interface TaskListProps {
tasks: Task[];
onTaskUpdate: (task: Task) => Promise<void>;
onTaskCompletionToggle?: (task: Task) => void;
onTaskCreate?: (task: Task) => void;
onTaskDelete: (taskUid: string) => void;
projects: Project[];
hideProjectName?: boolean;
onToggleToday?: (taskId: number, task?: Task) => Promise<void>;
showCompletedTasks?: boolean;
isInCompletedSection?: boolean;
}
const TaskList: React.FC<TaskListProps> = ({
tasks,
onTaskUpdate,
onTaskCompletionToggle,
onTaskDelete,
projects,
hideProjectName = false,
onToggleToday,
showCompletedTasks = false,
isInCompletedSection = false,
}) => {
// Conditionally filter tasks based on showCompletedTasks prop
const filteredTasks = showCompletedTasks
? tasks
: tasks.filter((task) => {
const isCompleted =
task.status === 'done' ||
task.status === 'archived' ||
task.status === 2 ||
task.status === 3;
return !isCompleted;
});
return (
<div className="task-list-container space-y-1.5 overflow-visible">
{filteredTasks.length > 0 ? (
filteredTasks.map((task) => (
<div
key={task.id}
className="task-item-wrapper transition-all duration-200 ease-in-out overflow-visible relative hover:z-[10000] focus-within:z-[10000]"
data-testid={`task-item-${task.id}`}
>
<TaskItem
task={task}
onTaskUpdate={onTaskUpdate}
onTaskCompletionToggle={onTaskCompletionToggle}
onTaskDelete={onTaskDelete}
projects={projects}
hideProjectName={hideProjectName}
onToggleToday={onToggleToday}
isInCompletedSection={isInCompletedSection}
/>
</div>
))
) : (
<p className="text-gray-500 dark:text-gray-400 text-center mt-4">
No tasks available.
</p>
)}
</div>
);
};
export default TaskList;