Fix recur instance done (#727)
* Fix recur instance done * Fix completed not showing
This commit is contained in:
parent
3fe694d1da
commit
b6ecdbec90
6 changed files with 89 additions and 12 deletions
|
|
@ -333,7 +333,8 @@ async function fetchTasksCompletedToday(userId, userTimezone) {
|
|||
const safeTimezone = getSafeTimezone(userTimezone);
|
||||
const todayBounds = getTodayBoundsInUTC(safeTimezone);
|
||||
|
||||
return await Task.findAll({
|
||||
// Fetch regular completed tasks
|
||||
const regularCompletedTasks = await Task.findAll({
|
||||
where: {
|
||||
user_id: userId,
|
||||
status: Task.STATUS.DONE,
|
||||
|
|
@ -345,8 +346,57 @@ async function fetchTasksCompletedToday(userId, userTimezone) {
|
|||
},
|
||||
},
|
||||
include: getTaskIncludeConfig(),
|
||||
order: [['completed_at', 'DESC']],
|
||||
});
|
||||
|
||||
// Fetch recurring tasks completed today via recurring_completions table
|
||||
const { RecurringCompletion } = require('../../../models');
|
||||
const recurringCompletions = await RecurringCompletion.findAll({
|
||||
where: {
|
||||
completed_at: {
|
||||
[Op.gte]: todayBounds.start,
|
||||
[Op.lte]: todayBounds.end,
|
||||
},
|
||||
skipped: false,
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Task,
|
||||
as: 'Task',
|
||||
where: {
|
||||
user_id: userId,
|
||||
parent_task_id: null,
|
||||
},
|
||||
include: getTaskIncludeConfig(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Extract the tasks from recurring completions and add completed_at and status
|
||||
const recurringCompletedTasks = recurringCompletions.map((rc) => {
|
||||
const task = rc.Task;
|
||||
// Add virtual completed_at and status for display purposes
|
||||
task.dataValues.completed_at = rc.completed_at;
|
||||
task.dataValues.status = Task.STATUS.DONE;
|
||||
// Also set the direct property to ensure it's accessible
|
||||
task.status = Task.STATUS.DONE;
|
||||
task.completed_at = rc.completed_at;
|
||||
return task;
|
||||
});
|
||||
|
||||
// Combine both lists
|
||||
const allCompletedTasks = [
|
||||
...regularCompletedTasks,
|
||||
...recurringCompletedTasks,
|
||||
];
|
||||
|
||||
// Sort by completed_at DESC
|
||||
allCompletedTasks.sort((a, b) => {
|
||||
const aTime = a.completed_at || a.dataValues.completed_at;
|
||||
const bTime = b.completed_at || b.dataValues.completed_at;
|
||||
return new Date(bTime) - new Date(aTime);
|
||||
});
|
||||
|
||||
return allCompletedTasks;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
|
|
@ -338,7 +338,10 @@ const GroupedTaskList: React.FC<GroupedTaskListProps> = ({
|
|||
{/* Day column tasks */}
|
||||
<div className="space-y-1.5">
|
||||
{dayTasks.map((task) => (
|
||||
<div key={task.id}>
|
||||
<div
|
||||
key={task.id}
|
||||
className="relative hover:z-[10000] focus-within:z-[10000]"
|
||||
>
|
||||
<TaskItem
|
||||
task={task}
|
||||
onTaskUpdate={
|
||||
|
|
@ -437,7 +440,7 @@ const GroupedTaskList: React.FC<GroupedTaskListProps> = ({
|
|||
{projectTasks.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="task-item-wrapper transition-all duration-200 ease-in-out"
|
||||
className="task-item-wrapper transition-all duration-200 ease-in-out relative hover:z-[10000] focus-within:z-[10000]"
|
||||
>
|
||||
<TaskItem
|
||||
task={task}
|
||||
|
|
@ -459,7 +462,7 @@ const GroupedTaskList: React.FC<GroupedTaskListProps> = ({
|
|||
: standaloneTask.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="task-item-wrapper transition-all duration-200 ease-in-out"
|
||||
className="task-item-wrapper transition-all duration-200 ease-in-out relative hover:z-[10000] focus-within:z-[10000]"
|
||||
>
|
||||
<TaskItem
|
||||
task={task}
|
||||
|
|
@ -488,7 +491,7 @@ const GroupedTaskList: React.FC<GroupedTaskListProps> = ({
|
|||
>
|
||||
{/* Show template only if it's not virtual */}
|
||||
{!isVirtualTemplate && (
|
||||
<div className="relative">
|
||||
<div className="relative hover:z-[10000] focus-within:z-[10000]">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-1">
|
||||
<TaskItem
|
||||
|
|
@ -569,7 +572,7 @@ const GroupedTaskList: React.FC<GroupedTaskListProps> = ({
|
|||
.map((instance) => (
|
||||
<div
|
||||
key={instance.id}
|
||||
className="opacity-75 hover:opacity-100 transition-opacity"
|
||||
className="opacity-75 hover:opacity-100 focus-within:opacity-100 transition-opacity relative hover:z-[10000] focus-within:z-[10000]"
|
||||
>
|
||||
<TaskItem
|
||||
task={instance}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,9 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
|||
>
|
||||
{/* Full view (md and larger) */}
|
||||
<div className="hidden md:flex flex-col md:flex-row md:items-center md:relative">
|
||||
<div className="flex items-center space-x-3 mb-2 md:mb-0 flex-1 min-w-0 pr-44">
|
||||
<div
|
||||
className={`flex items-center space-x-3 mb-2 md:mb-0 flex-1 min-w-0 ${!isUpcomingView ? 'pr-44' : ''}`}
|
||||
>
|
||||
<div className="hidden">
|
||||
<TaskPriorityIcon
|
||||
priority={task.priority}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const TaskList: React.FC<TaskListProps> = ({
|
|||
filteredTasks.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="task-item-wrapper transition-all duration-200 ease-in-out overflow-visible"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -333,7 +333,9 @@ const TaskStatusControl: React.FC<TaskStatusControlProps> = ({
|
|||
const completionButtonLabel = statusDisplay.label;
|
||||
|
||||
return (
|
||||
<div className={`relative ${className}`}>
|
||||
<div
|
||||
className={`relative ${completionMenuOpen ? 'z-[10000]' : ''} ${className}`}
|
||||
>
|
||||
<div
|
||||
className={`inline-flex items-stretch ${containerRoundedClass} border ${statusBorderColorClass} overflow-hidden ${hoverRevealQuickActions ? 'group' : ''}`}
|
||||
ref={desktopCompletionMenuRef}
|
||||
|
|
@ -410,7 +412,7 @@ const TaskStatusControl: React.FC<TaskStatusControlProps> = ({
|
|||
</div>
|
||||
{completionMenuOpen === 'desktop' && (
|
||||
<div
|
||||
className={`absolute right-0 top-full mt-1 w-48 bg-white dark:bg-gray-900 border ${statusBorderColorClass} rounded-lg shadow-lg z-[9999]`}
|
||||
className={`absolute right-0 top-full mt-1 w-48 bg-white dark:bg-gray-900 border ${statusBorderColorClass} rounded-lg shadow-lg z-[9999] opacity-100`}
|
||||
>
|
||||
{renderStatusMenuOptions('desktop')}
|
||||
</div>
|
||||
|
|
@ -497,7 +499,7 @@ const TaskStatusControl: React.FC<TaskStatusControlProps> = ({
|
|||
</div>
|
||||
{completionMenuOpen === 'mobile' && (
|
||||
<div
|
||||
className={`absolute right-0 top-full mt-1 w-48 bg-white dark:bg-gray-900 border ${statusBorderColorClass} rounded-lg shadow-lg z-[9999]`}
|
||||
className={`absolute right-0 top-full mt-1 w-48 bg-white dark:bg-gray-900 border ${statusBorderColorClass} rounded-lg shadow-lg z-[9999] opacity-100`}
|
||||
>
|
||||
{renderStatusMenuOptions('mobile')}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1024,6 +1024,26 @@ const TasksToday: React.FC = () => {
|
|||
// The updatedTask is already the result of the API call from TaskItem
|
||||
// Use the centralized task update handler to update UI optimistically
|
||||
await handleTaskUpdate(updatedTask);
|
||||
|
||||
// Check if this was a recurring task completion that needs refresh
|
||||
// Recurring tasks get advanced after completion, so they won't appear in completed list
|
||||
// without a refetch
|
||||
const isRecurringParent =
|
||||
updatedTask.recurrence_type &&
|
||||
updatedTask.recurrence_type !== 'none' &&
|
||||
!updatedTask.recurring_parent_id;
|
||||
|
||||
if (isRecurringParent) {
|
||||
// Refetch tasks to get the updated completed list for recurring tasks
|
||||
const result = await fetchTasks('?type=today');
|
||||
if (isMounted.current) {
|
||||
setMetrics((prevMetrics) => ({
|
||||
...prevMetrics,
|
||||
tasks_completed_today:
|
||||
result.tasks_completed_today || [],
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error toggling task completion:', error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue