(showNewTeam = false)}
+ onkeydown={(e) => e.key === "Escape" && (showNewTeam = false)}
+ role="dialog"
+ aria-label="Create Team dialog"
+ tabindex="-1"
>
e.stopPropagation()}
>
(null);
+ let originalColumnIdForTask = $state(null);
let editingCardId = $state(null);
let newTask = $state({
@@ -148,6 +149,8 @@
color: "neutral",
dueDate: "",
assignees: [] as string[],
+ estimatedMinutes: "",
+ actualMinutes: "",
subtasks: [] as { id: number; text: string; done: boolean }[],
});
@@ -200,6 +203,7 @@
function openCreateTaskModal(columnId: string) {
activeColumnIdForNewTask = columnId;
+ originalColumnIdForTask = columnId;
editingCardId = null;
newTask = {
title: "",
@@ -208,6 +212,8 @@
color: "neutral",
dueDate: "",
assignees: [],
+ estimatedMinutes: "",
+ actualMinutes: "",
subtasks: [],
};
assigneeInput = "";
@@ -217,6 +223,7 @@
function openEditTaskModal(columnId: string, card: LocalCard) {
activeColumnIdForNewTask = columnId;
+ originalColumnIdForTask = columnId;
editingCardId = card.id;
newTask = {
title: card.title,
@@ -225,6 +232,8 @@
color: card.color || "neutral",
dueDate: card.due_date ? card.due_date.split("T")[0] : "",
assignees: [...(card.assignees || [])],
+ estimatedMinutes: card.estimated_minutes?.toString() || "",
+ actualMinutes: card.actual_minutes?.toString() || "",
subtasks: card.subtasks.map((st) => ({ ...st })),
};
assigneeInput = "";
@@ -257,15 +266,42 @@
color: newTask.color,
due_date: newTask.dueDate,
assignees: newTask.assignees,
+ estimated_minutes: newTask.estimatedMinutes
+ ? parseInt(newTask.estimatedMinutes)
+ : undefined,
+ actual_minutes: newTask.actualMinutes
+ ? parseInt(newTask.actualMinutes)
+ : undefined,
subtasks: newTask.subtasks.map((st) => ({
id: st.id,
text: st.text,
done: st.done,
})),
});
- targetCol.cards = targetCol.cards.map((card) =>
- card.id === editingCardId
- ? {
+
+ if (originalColumnIdForTask === activeColumnIdForNewTask) {
+ targetCol.cards = targetCol.cards.map((card) =>
+ card.id === editingCardId
+ ? {
+ ...card,
+ ...updated,
+ subtasks: (updated.subtasks ?? []).map((st) => ({
+ id: st.id,
+ text: st.text,
+ done: st.done,
+ })),
+ }
+ : card,
+ );
+ } else {
+ const oldCol = columns.find((c) => c.id === originalColumnIdForTask);
+ if (oldCol) {
+ const cardIndex = oldCol.cards.findIndex(
+ (c) => c.id === editingCardId,
+ );
+ if (cardIndex !== -1) {
+ const [card] = oldCol.cards.splice(cardIndex, 1);
+ const formattedCard = {
...card,
...updated,
subtasks: (updated.subtasks ?? []).map((st) => ({
@@ -273,9 +309,18 @@
text: st.text,
done: st.done,
})),
- }
- : card,
- );
+ };
+ targetCol.cards.push(formattedCard);
+ await cardsApi
+ .move(
+ editingCardId,
+ activeColumnIdForNewTask!,
+ targetCol.cards.length - 1,
+ )
+ .catch(() => {});
+ }
+ }
+ }
} else {
const created = await boardApi.createCard(
boardId,
@@ -287,6 +332,12 @@
color: newTask.color,
due_date: newTask.dueDate || "",
assignees: newTask.assignees,
+ estimated_minutes: newTask.estimatedMinutes
+ ? parseInt(newTask.estimatedMinutes)
+ : undefined,
+ actual_minutes: newTask.actualMinutes
+ ? parseInt(newTask.actualMinutes)
+ : undefined,
},
);
targetCol.cards = [...targetCol.cards, { ...created, subtasks: [] }];
@@ -561,8 +612,8 @@
ondragstart={(e) => handleDragStart(card.id, column.id, e)}
class="bg-neutral-750 p-4 rounded-md border border-neutral-600 shadow-sm {isArchived
? 'cursor-default'
- : 'cursor-grab active:cursor-grabbing'} hover:border-neutral-500 transition-colors flex flex-col gap-2 group relative overflow-hidden"
- role="listitem"
+ : 'cursor-pointer hover:border-neutral-500'} transition-colors flex flex-col gap-2 group relative overflow-hidden"
+ role="button"
onclick={() =>
!isArchived && openEditTaskModal(column.id, card)}
onkeydown={(e) =>
@@ -642,6 +693,20 @@
)}
{/if}
+ {#if card.estimated_minutes || card.actual_minutes}
+
+
+ {card.actual_minutes || 0}m / {card.estimated_minutes ||
+ "?"}m
+
+ {/if}