Fix saving subtasks on edit (#806)
This commit is contained in:
parent
e7f23bcff8
commit
2f13d0d4a7
3 changed files with 84 additions and 196 deletions
|
|
@ -10,6 +10,7 @@ import {
|
|||
deleteTask,
|
||||
fetchTaskByUid,
|
||||
fetchTaskNextIterations,
|
||||
fetchSubtasks,
|
||||
TaskIteration,
|
||||
toggleTaskCompletion,
|
||||
} from '../../utils/tasksService';
|
||||
|
|
@ -57,8 +58,7 @@ const TaskDetails: React.FC = () => {
|
|||
const [loadingIterations, setLoadingIterations] = useState(false);
|
||||
const [parentTask, setParentTask] = useState<Task | null>(null);
|
||||
const [loadingParent, setLoadingParent] = useState(false);
|
||||
const [isEditingSubtasks, setIsEditingSubtasks] = useState(false);
|
||||
const [editedSubtasks, setEditedSubtasks] = useState<Task[]>([]);
|
||||
const [pendingSubtasks, setPendingSubtasks] = useState<Task[]>([]);
|
||||
const [actionsMenuOpen, setActionsMenuOpen] = useState(false);
|
||||
const actionsMenuRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
|
|
@ -116,6 +116,7 @@ const TaskDetails: React.FC = () => {
|
|||
});
|
||||
const [activePill, setActivePill] = useState('overview');
|
||||
const [attachmentCount, setAttachmentCount] = useState(0);
|
||||
const [hasLoadedSubtasks, setHasLoadedSubtasks] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setEditedDueDate(task?.due_date || '');
|
||||
|
|
@ -187,7 +188,6 @@ const TaskDetails: React.FC = () => {
|
|||
setRecurrenceForm((prev) => {
|
||||
const updated = { ...prev, [field]: value };
|
||||
|
||||
// Set default values when switching to monthly recurrence
|
||||
if (
|
||||
field === 'recurrence_type' &&
|
||||
value === 'monthly' &&
|
||||
|
|
@ -307,7 +307,6 @@ const TaskDetails: React.FC = () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if due date is in the past
|
||||
if (editedDueDate) {
|
||||
const dueDate = new Date(editedDueDate);
|
||||
const today = new Date();
|
||||
|
|
@ -463,7 +462,6 @@ const TaskDetails: React.FC = () => {
|
|||
fetchTaskData();
|
||||
}, [uid, task, tasksStore]);
|
||||
|
||||
// Load attachment count when task is loaded
|
||||
useEffect(() => {
|
||||
const loadAttachmentCount = async () => {
|
||||
if (task?.uid) {
|
||||
|
|
@ -479,6 +477,49 @@ const TaskDetails: React.FC = () => {
|
|||
loadAttachmentCount();
|
||||
}, [task?.uid]);
|
||||
|
||||
useEffect(() => {
|
||||
setHasLoadedSubtasks(false);
|
||||
}, [uid]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadSubtasks = async () => {
|
||||
const subtasksAlreadyLoaded = task?.subtasks && task.subtasks.length > 0;
|
||||
|
||||
if (
|
||||
activePill === 'subtasks' &&
|
||||
task?.uid &&
|
||||
!hasLoadedSubtasks &&
|
||||
!subtasksAlreadyLoaded
|
||||
) {
|
||||
try {
|
||||
const fetchedSubtasks = await fetchSubtasks(task.uid);
|
||||
setHasLoadedSubtasks(true);
|
||||
|
||||
const existingIndex = tasksStore.tasks.findIndex(
|
||||
(t: Task) => t.uid === task.uid
|
||||
);
|
||||
if (existingIndex >= 0) {
|
||||
const updatedTasks = [...tasksStore.tasks];
|
||||
updatedTasks[existingIndex] = {
|
||||
...task,
|
||||
subtasks: fetchedSubtasks,
|
||||
};
|
||||
tasksStore.setTasks(updatedTasks);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading subtasks:', error);
|
||||
setHasLoadedSubtasks(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
loadSubtasks();
|
||||
}, [activePill, task?.uid, task?.subtasks, hasLoadedSubtasks, tasksStore]);
|
||||
|
||||
useEffect(() => {
|
||||
setPendingSubtasks(subtasks);
|
||||
}, [subtasks]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadNextIterations = async () => {
|
||||
if (
|
||||
|
|
@ -488,7 +529,6 @@ const TaskDetails: React.FC = () => {
|
|||
) {
|
||||
try {
|
||||
setLoadingIterations(true);
|
||||
// Don't pass startFromDate - let backend default to today
|
||||
const iterations = await fetchTaskNextIterations(
|
||||
task.uid!
|
||||
);
|
||||
|
|
@ -508,7 +548,6 @@ const TaskDetails: React.FC = () => {
|
|||
try {
|
||||
setLoadingIterations(true);
|
||||
|
||||
// Don't pass startFromDate - let backend default to today
|
||||
const iterations = await fetchTaskNextIterations(
|
||||
parentTask.uid
|
||||
);
|
||||
|
|
@ -559,20 +598,29 @@ const TaskDetails: React.FC = () => {
|
|||
loadParentTask();
|
||||
}, [task?.recurring_parent_uid]);
|
||||
|
||||
const handleStartSubtasksEdit = () => {
|
||||
setIsEditingSubtasks(true);
|
||||
setEditedSubtasks([...subtasks]);
|
||||
};
|
||||
|
||||
const handleSaveSubtasks = async () => {
|
||||
const handleSaveSubtasks = async (subtasksToSave: Task[]) => {
|
||||
if (!task?.uid) {
|
||||
setIsEditingSubtasks(false);
|
||||
setEditedSubtasks([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const hasChanges =
|
||||
subtasksToSave.length !== subtasks.length ||
|
||||
subtasksToSave.some(
|
||||
(ps, i) =>
|
||||
!subtasks[i] ||
|
||||
ps.name !== subtasks[i].name ||
|
||||
ps.status !== subtasks[i].status ||
|
||||
(ps as any)._isNew ||
|
||||
(ps as any)._isEdited ||
|
||||
(ps as any)._statusChanged
|
||||
);
|
||||
|
||||
if (!hasChanges) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await updateTask(task.uid, { ...task, subtasks: editedSubtasks });
|
||||
await updateTask(task.uid, { ...task, subtasks: subtasksToSave });
|
||||
|
||||
if (uid) {
|
||||
const updatedTask = await fetchTaskByUid(uid);
|
||||
|
|
@ -586,45 +634,13 @@ const TaskDetails: React.FC = () => {
|
|||
}
|
||||
}
|
||||
|
||||
showSuccessToast(
|
||||
t('task.subtasksUpdated', 'Subtasks updated successfully')
|
||||
);
|
||||
setIsEditingSubtasks(false);
|
||||
|
||||
setTimelineRefreshKey((prev) => prev + 1);
|
||||
} catch (error) {
|
||||
console.error('Error updating subtasks:', error);
|
||||
showErrorToast(
|
||||
t('task.subtasksUpdateError', 'Failed to update subtasks')
|
||||
);
|
||||
setEditedSubtasks([...subtasks]);
|
||||
setIsEditingSubtasks(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelSubtasksEdit = () => {
|
||||
setIsEditingSubtasks(false);
|
||||
setEditedSubtasks([]);
|
||||
};
|
||||
|
||||
const handleToggleSubtaskCompletion = async (subtask: Task) => {
|
||||
if (!subtask.uid) return;
|
||||
try {
|
||||
await toggleTaskCompletion(subtask.uid, subtask);
|
||||
if (uid) {
|
||||
const updatedTask = await fetchTaskByUid(uid);
|
||||
const existingIndex = tasksStore.tasks.findIndex(
|
||||
(t: Task) => t.uid === uid
|
||||
);
|
||||
if (existingIndex >= 0) {
|
||||
const updatedTasks = [...tasksStore.tasks];
|
||||
updatedTasks[existingIndex] = updatedTask;
|
||||
tasksStore.setTasks(updatedTasks);
|
||||
}
|
||||
}
|
||||
setTimelineRefreshKey((prev) => prev + 1);
|
||||
} catch (error) {
|
||||
console.error('Error toggling subtask completion:', error);
|
||||
setPendingSubtasks([...subtasks]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -715,13 +731,11 @@ const TaskDetails: React.FC = () => {
|
|||
try {
|
||||
setLoadingIterations(true);
|
||||
if (isTemplateTask) {
|
||||
// Don't pass startFromDate - let backend default to today
|
||||
const iterations = await fetchTaskNextIterations(
|
||||
latestTask.uid!
|
||||
);
|
||||
setNextIterations(iterations);
|
||||
} else if (canUseParentIterations && parentTask?.uid) {
|
||||
// Don't pass startFromDate - let backend default to today
|
||||
const iterations = await fetchTaskNextIterations(
|
||||
parentTask.uid
|
||||
);
|
||||
|
|
@ -1071,7 +1085,6 @@ const TaskDetails: React.FC = () => {
|
|||
return (
|
||||
<div className="px-4 lg:px-6 pt-4">
|
||||
<div className="w-full">
|
||||
{/* Header Section with Title and Action Buttons */}
|
||||
<TaskDetailsHeader
|
||||
task={task}
|
||||
onTitleUpdate={handleTitleUpdate}
|
||||
|
|
@ -1092,12 +1105,9 @@ const TaskDetails: React.FC = () => {
|
|||
subtasksCount={subtasks.length}
|
||||
/>
|
||||
|
||||
{/* Content - Full width layout */}
|
||||
<div className="mb-6 mt-6">
|
||||
{/* Overview Pill */}
|
||||
{activePill === 'overview' && (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
|
||||
{/* Left Column - Main Content */}
|
||||
<div className="lg:col-span-3 space-y-8">
|
||||
<TaskContentCard
|
||||
content={task.note || ''}
|
||||
|
|
@ -1105,7 +1115,6 @@ const TaskDetails: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* Right Column - Project and Tags */}
|
||||
<div className="space-y-6">
|
||||
<TaskProjectCard
|
||||
task={task}
|
||||
|
|
@ -1151,7 +1160,6 @@ const TaskDetails: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Recurrence Pill */}
|
||||
{activePill === 'recurrence' && (
|
||||
<div className="grid grid-cols-1">
|
||||
<TaskRecurrenceCard
|
||||
|
|
@ -1171,26 +1179,17 @@ const TaskDetails: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Subtasks Pill */}
|
||||
{activePill === 'subtasks' && (
|
||||
<div className="grid grid-cols-1">
|
||||
<TaskSubtasksCard
|
||||
task={task}
|
||||
subtasks={subtasks}
|
||||
isEditing={isEditingSubtasks}
|
||||
editedSubtasks={editedSubtasks}
|
||||
onSubtasksChange={setEditedSubtasks}
|
||||
onStartEdit={handleStartSubtasksEdit}
|
||||
subtasks={pendingSubtasks}
|
||||
onSubtasksChange={setPendingSubtasks}
|
||||
onSave={handleSaveSubtasks}
|
||||
onCancel={handleCancelSubtasksEdit}
|
||||
onToggleSubtaskCompletion={
|
||||
handleToggleSubtaskCompletion
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Attachments Pill */}
|
||||
{activePill === 'attachments' && (
|
||||
<div className="grid grid-cols-1">
|
||||
<TaskAttachmentsCard
|
||||
|
|
@ -1200,7 +1199,6 @@ const TaskDetails: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Activity Pill */}
|
||||
{activePill === 'activity' && (
|
||||
<div className="rounded-lg shadow-sm bg-white dark:bg-gray-900 border-2 border-gray-50 dark:border-gray-800 p-6">
|
||||
<TaskTimeline
|
||||
|
|
@ -1210,9 +1208,7 @@ const TaskDetails: React.FC = () => {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* End of main content sections */}
|
||||
|
||||
{/* Confirm Delete Dialog */}
|
||||
{isConfirmDialogOpen && taskToDelete && (
|
||||
<ConfirmDialog
|
||||
title={t('task.deleteConfirmTitle', 'Delete Task')}
|
||||
|
|
|
|||
|
|
@ -1,119 +1,28 @@
|
|||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ListBulletIcon } from '@heroicons/react/24/outline';
|
||||
import TaskSubtasksSection from '../TaskForm/TaskSubtasksSection';
|
||||
import TaskPriorityIcon from '../../Shared/Icons/TaskPriorityIcon';
|
||||
import { Task } from '../../../entities/Task';
|
||||
|
||||
interface TaskSubtasksCardProps {
|
||||
task: Task;
|
||||
subtasks: Task[];
|
||||
isEditing: boolean;
|
||||
editedSubtasks: Task[];
|
||||
onSubtasksChange: (subtasks: Task[]) => void;
|
||||
onStartEdit: () => void;
|
||||
onSave: () => void;
|
||||
onCancel: () => void;
|
||||
onToggleSubtaskCompletion: (subtask: Task) => Promise<void>;
|
||||
onSave: (subtasks: Task[]) => void;
|
||||
}
|
||||
|
||||
const TaskSubtasksCard: React.FC<TaskSubtasksCardProps> = ({
|
||||
task,
|
||||
subtasks,
|
||||
isEditing,
|
||||
editedSubtasks,
|
||||
onSubtasksChange,
|
||||
onStartEdit,
|
||||
onSave,
|
||||
onCancel,
|
||||
onToggleSubtaskCompletion,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
{isEditing ? (
|
||||
<div className="rounded-lg shadow-sm bg-white dark:bg-gray-900 border-2 border-blue-500 dark:border-blue-400 p-6">
|
||||
<TaskSubtasksSection
|
||||
parentTaskId={task.id!}
|
||||
subtasks={editedSubtasks}
|
||||
onSubtasksChange={onSubtasksChange}
|
||||
/>
|
||||
<div className="flex items-center justify-end mt-4 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
onClick={onSave}
|
||||
className="px-4 py-2 text-sm bg-green-600 dark:bg-green-500 text-white rounded hover:bg-green-700 dark:hover:bg-green-600 transition-colors"
|
||||
>
|
||||
{t('common.save', 'Save')}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
className="px-4 py-2 text-sm bg-gray-200 dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded hover:bg-gray-300 dark:hover:bg-gray-700 transition-colors"
|
||||
>
|
||||
{t('common.cancel', 'Cancel')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : subtasks.length > 0 ? (
|
||||
<div className="space-y-0.5">
|
||||
{subtasks.map((subtask: Task) => (
|
||||
<div
|
||||
key={subtask.id}
|
||||
className={`rounded-lg shadow-sm bg-white dark:bg-gray-900 border transition-all duration-200 ${
|
||||
subtask.status === 'in_progress' ||
|
||||
subtask.status === 1
|
||||
? 'border-blue-500/60 dark:border-blue-600/60'
|
||||
: 'border-gray-50 dark:border-gray-800'
|
||||
}`}
|
||||
>
|
||||
<div className="px-3 py-3 flex items-center space-x-3">
|
||||
<TaskPriorityIcon
|
||||
priority={subtask.priority}
|
||||
status={subtask.status}
|
||||
onToggleCompletion={() =>
|
||||
onToggleSubtaskCompletion(subtask)
|
||||
}
|
||||
/>
|
||||
<span
|
||||
onClick={onStartEdit}
|
||||
className={`text-base flex-1 truncate cursor-pointer hover:text-blue-600 dark:hover:text-blue-400 transition-colors ${
|
||||
subtask.status === 'done' ||
|
||||
subtask.status === 2 ||
|
||||
subtask.status === 'archived' ||
|
||||
subtask.status === 3
|
||||
? 'text-gray-500 dark:text-gray-400'
|
||||
: 'text-gray-900 dark:text-gray-100'
|
||||
}`}
|
||||
title={t(
|
||||
'task.clickToEditSubtasks',
|
||||
'Click to edit subtasks'
|
||||
)}
|
||||
>
|
||||
{subtask.name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
onClick={onStartEdit}
|
||||
className="rounded-lg shadow-sm bg-white dark:bg-gray-900 border-2 border-gray-50 dark:border-gray-800 hover:border-gray-200 dark:hover:border-gray-700 p-6 cursor-pointer transition-colors"
|
||||
title={t(
|
||||
'task.clickToEditSubtasks',
|
||||
'Click to add or edit subtasks'
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center py-8 text-gray-500 dark:text-gray-400">
|
||||
<ListBulletIcon className="h-12 w-12 mb-3 opacity-50" />
|
||||
<span className="text-sm text-center">
|
||||
{t('task.noSubtasksClickToAdd', 'Add subtasks')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="rounded-lg shadow-sm bg-white dark:bg-gray-900 border-2 border-gray-50 dark:border-gray-800 p-6">
|
||||
<TaskSubtasksSection
|
||||
parentTaskId={task.id!}
|
||||
subtasks={subtasks}
|
||||
onSubtasksChange={onSubtasksChange}
|
||||
onSave={onSave}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ interface TaskSubtasksSectionProps {
|
|||
subtasks: Task[];
|
||||
onSubtasksChange: (subtasks: Task[]) => void;
|
||||
onSubtaskUpdate?: (subtask: Task) => Promise<void>;
|
||||
onSave?: (subtasks: Task[]) => void;
|
||||
}
|
||||
|
||||
const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
||||
|
|
@ -17,6 +18,7 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
subtasks,
|
||||
onSubtasksChange,
|
||||
onSubtaskUpdate,
|
||||
onSave,
|
||||
}) => {
|
||||
const [newSubtaskName, setNewSubtaskName] = useState('');
|
||||
const [isLoading] = useState(false);
|
||||
|
|
@ -28,7 +30,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
|
||||
const scrollToBottom = () => {
|
||||
setTimeout(() => {
|
||||
// Find the modal's scrollable container
|
||||
const modalScrollContainer = document.querySelector(
|
||||
'.absolute.inset-0.overflow-y-auto'
|
||||
);
|
||||
|
|
@ -49,24 +50,24 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
status: 'not_started',
|
||||
priority: 'low',
|
||||
today: false,
|
||||
parent_task_id: parentTaskId, // Set the parent task ID immediately
|
||||
// Mark as new for backend processing
|
||||
parent_task_id: parentTaskId,
|
||||
isNew: true,
|
||||
// Also keep for UI purposes
|
||||
_isNew: true,
|
||||
completed_at: null,
|
||||
} as Task;
|
||||
|
||||
onSubtasksChange([...subtasks, newSubtask]);
|
||||
const updatedSubtasks = [...subtasks, newSubtask];
|
||||
onSubtasksChange(updatedSubtasks);
|
||||
setNewSubtaskName('');
|
||||
|
||||
// Only scroll when adding new subtask, not when toggling completion
|
||||
scrollToBottom();
|
||||
|
||||
onSave?.(updatedSubtasks);
|
||||
};
|
||||
|
||||
const handleDeleteSubtask = (index: number) => {
|
||||
const updatedSubtasks = subtasks.filter((_, i) => i !== index);
|
||||
onSubtasksChange(updatedSubtasks);
|
||||
onSave?.(updatedSubtasks);
|
||||
};
|
||||
|
||||
const handleKeyPress = (e: React.KeyboardEvent) => {
|
||||
|
|
@ -93,10 +94,8 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
return {
|
||||
...subtask,
|
||||
name: editingName.trim(),
|
||||
// Backend flags
|
||||
isNew: isNew,
|
||||
isEdited: isEdited,
|
||||
// UI flags
|
||||
_isNew: isNew,
|
||||
_isEdited: isEdited,
|
||||
};
|
||||
|
|
@ -107,6 +106,7 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
onSubtasksChange(updatedSubtasks);
|
||||
setEditingIndex(null);
|
||||
setEditingName('');
|
||||
onSave?.(updatedSubtasks);
|
||||
};
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
|
|
@ -130,7 +130,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
...subtask,
|
||||
status: newStatus,
|
||||
completed_at: isDone ? null : new Date().toISOString(),
|
||||
// Mark for backend update if it has an ID (existing subtask)
|
||||
_statusChanged: hasId,
|
||||
};
|
||||
}
|
||||
|
|
@ -141,7 +140,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
|
||||
return (
|
||||
<div ref={subtasksSectionRef} className="space-y-3">
|
||||
{/* Existing Subtasks */}
|
||||
{isLoading ? (
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
{t('loading.subtasks', 'Loading subtasks...')}
|
||||
|
|
@ -171,7 +169,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
(subtask as any).isNew
|
||||
)
|
||||
) {
|
||||
// Existing subtask - use API for immediate toggle, then update callback
|
||||
try {
|
||||
const updatedSubtask =
|
||||
await toggleTaskCompletion(
|
||||
|
|
@ -187,7 +184,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
);
|
||||
}
|
||||
} else {
|
||||
// New subtask or no callback - handle locally
|
||||
handleToggleNewSubtaskCompletion(
|
||||
index
|
||||
);
|
||||
|
|
@ -245,7 +241,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
.isNew
|
||||
)
|
||||
) {
|
||||
// Existing subtask - use API for immediate toggle, then update callback
|
||||
try {
|
||||
const updatedSubtask =
|
||||
await toggleTaskCompletion(
|
||||
|
|
@ -261,7 +256,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
);
|
||||
}
|
||||
} else {
|
||||
// New subtask or no callback - handle locally
|
||||
handleToggleNewSubtaskCompletion(
|
||||
index
|
||||
);
|
||||
|
|
@ -287,16 +281,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
)}
|
||||
>
|
||||
{subtask.name}
|
||||
{(subtask as any)._isNew && (
|
||||
<span className="ml-2 text-xs text-blue-500 dark:text-blue-400">
|
||||
(new)
|
||||
</span>
|
||||
)}
|
||||
{(subtask as any)._isEdited && (
|
||||
<span className="ml-2 text-xs text-orange-500 dark:text-orange-400">
|
||||
(edited)
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
|
|
@ -320,7 +304,6 @@ const TaskSubtasksSection: React.FC<TaskSubtasksSectionProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Add New Subtask */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<input
|
||||
ref={addInputRef}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue