diff --git a/app/task/[id].tsx b/app/task/[id].tsx index 245900c..a540f1a 100644 --- a/app/task/[id].tsx +++ b/app/task/[id].tsx @@ -54,6 +54,7 @@ type TaskData = { priority: number; dueDate: Date | null; listId: string; + parentId: string | null; recurrence: string | null; }; @@ -400,67 +401,71 @@ export default function TaskDetailScreen() { )} - {/* Subtasks */} - - {t('task.subtasks')} - - {subtasks.map((sub) => ( - editingSubtaskId === sub.id ? undefined : handleToggleSubtask(sub.id)} - onLongPress={() => handleEditSubtask(sub)} - className={`flex-row items-center border-b py-2.5 ${isDark ? 'border-[#3A3A3A]' : 'border-[#E5E7EB]'}`} - > - - {sub.completed && } - - {editingSubtaskId === sub.id ? ( + {/* Subtasks — only for root tasks (not subtasks themselves) */} + {!task?.parentId && ( + <> + + {t('task.subtasks')} + + {subtasks.map((sub) => ( + editingSubtaskId === sub.id ? undefined : handleToggleSubtask(sub.id)} + onLongPress={() => handleEditSubtask(sub)} + className={`flex-row items-center border-b py-2.5 ${isDark ? 'border-[#3A3A3A]' : 'border-[#E5E7EB]'}`} + > + + {sub.completed && } + + {editingSubtaskId === sub.id ? ( + + ) : ( + + {sub.title} + + )} + handleDeleteSubtask(sub.id)} + className="ml-2 p-1.5" + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} + > + + + + ))} + + {/* Add subtask */} + + - ) : ( - - {sub.title} - - )} - handleDeleteSubtask(sub.id)} - className="ml-2 p-1.5" - hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} - > - - - - ))} - - {/* Add subtask */} - - - - + + + )} diff --git a/web/src/app/api/tasks/route.ts b/web/src/app/api/tasks/route.ts index aeaf4a2..ad9c9e7 100644 --- a/web/src/app/api/tasks/route.ts +++ b/web/src/app/api/tasks/route.ts @@ -25,16 +25,20 @@ export async function POST(request: Request) { return NextResponse.json({ error: 'List not found' }, { status: 404 }); } - // If parentId, verify parent task belongs to user + // If parentId, verify parent task belongs to user and is not itself a subtask if (body.data.parentId) { const [parent] = await db - .select({ id: slTasks.id }) + .select({ id: slTasks.id, parentId: slTasks.parentId }) .from(slTasks) .where(and(eq(slTasks.id, body.data.parentId), eq(slTasks.userId, auth.userId))); if (!parent) { return NextResponse.json({ error: 'Parent task not found' }, { status: 404 }); } + + if (parent.parentId) { + return NextResponse.json({ error: 'Cannot create sub-subtasks (max 2 levels)' }, { status: 400 }); + } } const [task] = await db diff --git a/web/src/components/TaskItem.tsx b/web/src/components/TaskItem.tsx index 16627e8..1d0d7a8 100644 --- a/web/src/components/TaskItem.tsx +++ b/web/src/components/TaskItem.tsx @@ -261,12 +261,14 @@ export function TaskItem({ task, subtasks = [], depth = 0 }: TaskItemProps) { > {t("task.edit")} - + {depth < 1 && ( + + )}