diff --git a/frontend/src/views/ProjectView.vue b/frontend/src/views/ProjectView.vue index 7787ec2..34509a2 100644 --- a/frontend/src/views/ProjectView.vue +++ b/frontend/src/views/ProjectView.vue @@ -65,6 +65,11 @@ const showNewMilestone = ref(false); const newMilestoneTitle = ref(""); const creatingMilestone = ref(false); +// Milestone edit/delete state +const renamingMilestoneId = ref(null); +const renamingMilestoneTitle = ref(""); +const deletingMilestone = ref(null); + // Edit state const editTitle = ref(""); const editDescription = ref(""); @@ -156,6 +161,38 @@ async function createMilestone() { } } +function startRenameMilestone(ms: Milestone) { + renamingMilestoneId.value = ms.id; + renamingMilestoneTitle.value = ms.title; +} + +async function commitRenameMilestone(ms: Milestone) { + const newTitle = renamingMilestoneTitle.value.trim(); + renamingMilestoneId.value = null; + if (!newTitle || newTitle === ms.title) return; + try { + await apiPatch(`/api/projects/${projectId.value}/milestones/${ms.id}`, { title: newTitle }); + await loadMilestones(); + toast.show("Milestone renamed"); + } catch { + toast.show("Failed to rename milestone", "error"); + } +} + +async function confirmDeleteMilestone() { + const ms = deletingMilestone.value; + if (!ms) return; + deletingMilestone.value = null; + try { + await apiDelete(`/api/projects/${projectId.value}/milestones/${ms.id}`); + await loadMilestones(); + await loadTasks(); + toast.show("Milestone deleted"); + } catch { + toast.show("Failed to delete milestone", "error"); + } +} + async function loadTasks() { tasksLoading.value = true; try { @@ -384,13 +421,25 @@ function formatDate(dateStr?: string | null): string {
{{ collapsedMilestones.has(group.milestone.id) ? '▶' : '▼' }} - {{ group.milestone?.title ?? "No Milestone" }} + + + {{ group.milestone?.title ?? "No Milestone" }} {{ group.tasks.length }}
@@ -497,7 +559,24 @@ function formatDate(dateStr?: string | null): string { - + + + + + +