From 0382657464bc57c489ca1bb575304fb975fd8cea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:29:00 +0000 Subject: [PATCH 1/3] Initial plan From ce480d354d599ed601625fe2b539847a7a697820 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:31:12 +0000 Subject: [PATCH 2/3] Add delete task feature - backend routes and controller Agent-Logs-Url: https://github.com/shobhit2603/Momentum/sessions/85ed2e0f-097d-414a-98c6-0f9a3e265067 Co-authored-by: shobhit2603 <149822769+shobhit2603@users.noreply.github.com> --- client/app/page.jsx | 22 +++++++++++++++++++++- server/src/controllers/task.controller.js | 21 +++++++++++++++++++++ server/src/dao/task.dao.js | 6 ++++++ server/src/routes/task.routes.js | 2 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/client/app/page.jsx b/client/app/page.jsx index cfc0a22..62f90a0 100644 --- a/client/app/page.jsx +++ b/client/app/page.jsx @@ -1,7 +1,7 @@ "use client"; import { useState, useEffect, useRef } from "react"; -import { CheckCircle, Circle, CircleHalf, Microphone, Plus, WarningCircle, Fire, CaretDown } from "@phosphor-icons/react"; +import { CheckCircle, Circle, CircleHalf, Microphone, Plus, WarningCircle, Fire, CaretDown, Trash } from "@phosphor-icons/react"; import { motion, AnimatePresence } from "motion/react"; import { fetchAPI } from "@/lib/api"; import { renderTaskItem } from "@/lib/taskRenderer"; @@ -139,6 +139,19 @@ export default function Dashboard() { }); }; + const deleteTask = async (taskId, e) => { + e.stopPropagation(); + if (!confirm("Are you sure you want to delete this task?")) return; + + const { status } = await fetchAPI(`/tasks/${taskId}`, { + method: "DELETE" + }); + + if (status === 200) { + setTasks(prev => prev.filter(t => t._id !== taskId)); + } + }; + const stopListening = () => { if (recognitionRef.current) { recognitionRef.current.stop(); @@ -303,6 +316,13 @@ export default function Dashboard() { {task.title} + )) )} diff --git a/server/src/controllers/task.controller.js b/server/src/controllers/task.controller.js index 686f7f5..e4e2c96 100644 --- a/server/src/controllers/task.controller.js +++ b/server/src/controllers/task.controller.js @@ -148,3 +148,24 @@ export const getAllFriendsTasks = async (req, res) => { }); } }; + +export const deleteTask = async (req, res) => { + try { + const { taskId } = req.params; + + const task = await taskDao.deleteTask(req.user.id, taskId); + + if (!task) { + return res + .status(404) + .json({ success: false, message: "Task not found" }); + } + + res.status(200).json({ success: true, message: "Task deleted successfully" }); + } catch (error) { + console.error("Error in deleteTask:", error); + res + .status(500) + .json({ success: false, message: "Server error deleting task" }); + } +}; diff --git a/server/src/dao/task.dao.js b/server/src/dao/task.dao.js index 93aa519..b76a1a0 100644 --- a/server/src/dao/task.dao.js +++ b/server/src/dao/task.dao.js @@ -35,3 +35,9 @@ export const getTasksForUsersByDateRange = async (userIds, start, end) => { .populate("userId", "name profilePicture streak") .sort({ createdAt: -1 }); }; + +export const deleteTask = async (userId, taskId) => { + return await Task.findOneAndDelete( + { _id: taskId, userId }, + ); +}; diff --git a/server/src/routes/task.routes.js b/server/src/routes/task.routes.js index 4767a89..b70ae38 100644 --- a/server/src/routes/task.routes.js +++ b/server/src/routes/task.routes.js @@ -7,6 +7,7 @@ import { getTaskHistory, getFriendTasks, getAllFriendsTasks, + deleteTask, } from "../controllers/task.controller.js"; const taskRouter = Router(); @@ -19,6 +20,7 @@ taskRouter.get("/today", getTodayTasks); taskRouter.get("/friends/today", getAllFriendsTasks); taskRouter.get("/history", getTaskHistory); taskRouter.patch("/:taskId/status", updateTaskStatus); +taskRouter.delete("/:taskId", deleteTask); taskRouter.get("/friend/:friendId/today", getFriendTasks); export default taskRouter; From 7cbc079f3e0cbe90c57ba2e87dd4798f448535fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:37:00 +0000 Subject: [PATCH 3/3] Add delete task feature - final implementation with custom confirmation modal Agent-Logs-Url: https://github.com/shobhit2603/Momentum/sessions/85ed2e0f-097d-414a-98c6-0f9a3e265067 Co-authored-by: shobhit2603 <149822769+shobhit2603@users.noreply.github.com> --- client/app/page.jsx | 74 ++++++++++++++++++++--- server/src/controllers/task.controller.js | 2 +- server/src/dao/task.dao.js | 2 +- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/client/app/page.jsx b/client/app/page.jsx index 62f90a0..6ef4791 100644 --- a/client/app/page.jsx +++ b/client/app/page.jsx @@ -14,6 +14,7 @@ export default function Dashboard() { const [timeLeft, setTimeLeft] = useState(""); const [errorMsg, setErrorMsg] = useState(""); const [expandedFriends, setExpandedFriends] = useState(new Set()); + const [deleteConfirm, setDeleteConfirm] = useState(null); const recognitionRef = useRef(null); @@ -139,17 +140,32 @@ export default function Dashboard() { }); }; - const deleteTask = async (taskId, e) => { - e.stopPropagation(); - if (!confirm("Are you sure you want to delete this task?")) return; - - const { status } = await fetchAPI(`/tasks/${taskId}`, { - method: "DELETE" - }); - - if (status === 200) { - setTasks(prev => prev.filter(t => t._id !== taskId)); + const showError = (message) => { + setErrorMsg(message); + setTimeout(() => setErrorMsg(""), 5000); + }; + + const performDeleteTask = async (taskId) => { + try { + const { status, data } = await fetchAPI(`/tasks/${taskId}`, { + method: "DELETE" + }); + + if (status === 200 && data.success) { + setTasks(prev => prev.filter(t => t._id !== taskId)); + } else { + showError("Failed to delete task. Please try again."); + } + } catch (error) { + console.error("Error deleting task:", error); + showError("Failed to delete task. Please try again."); } + setDeleteConfirm(null); + }; + + const deleteTask = (taskId, e) => { + e.stopPropagation(); + setDeleteConfirm(taskId); }; const stopListening = () => { @@ -229,6 +245,44 @@ export default function Dashboard() { )} + {/* Delete Confirmation Modal */} + + {deleteConfirm && ( + setDeleteConfirm(null)} + > + e.stopPropagation()} + className="glass-panel border border-border rounded-2xl p-6 max-w-sm mx-4" + > +

Delete Task?

+

This action cannot be undone. Are you sure you want to delete this task?

+
+ + +
+
+
+ )} +
+ {/* Main Tasks Area */}
diff --git a/server/src/controllers/task.controller.js b/server/src/controllers/task.controller.js index e4e2c96..6e5d04b 100644 --- a/server/src/controllers/task.controller.js +++ b/server/src/controllers/task.controller.js @@ -153,7 +153,7 @@ export const deleteTask = async (req, res) => { try { const { taskId } = req.params; - const task = await taskDao.deleteTask(req.user.id, taskId); + const task = await taskDao.deleteTaskById(req.user.id, taskId); if (!task) { return res diff --git a/server/src/dao/task.dao.js b/server/src/dao/task.dao.js index b76a1a0..de07ae8 100644 --- a/server/src/dao/task.dao.js +++ b/server/src/dao/task.dao.js @@ -36,7 +36,7 @@ export const getTasksForUsersByDateRange = async (userIds, start, end) => { .sort({ createdAt: -1 }); }; -export const deleteTask = async (userId, taskId) => { +export const deleteTaskById = async (userId, taskId) => { return await Task.findOneAndDelete( { _id: taskId, userId }, );