diff --git a/client/app/page.jsx b/client/app/page.jsx index cfc0a22..6ef4791 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"; @@ -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,6 +140,34 @@ export default function Dashboard() { }); }; + 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 = () => { if (recognitionRef.current) { recognitionRef.current.stop(); @@ -216,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 */}
@@ -303,6 +370,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..6e5d04b 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.deleteTaskById(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..de07ae8 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 deleteTaskById = 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;