const express = require("express"); const mongoose = require("mongoose"); const Task = require("../models/Task"); const User = require("../models/User"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createTaskValidation, taskIdValidation, } = require("../middleware/validators/taskValidator"); const { awardTaskCompletionPoints, checkAndAwardBadges, } = require("../services/gamificationService"); const router = express.Router(); // Get all tasks for user (with pagination) router.get( "/", auth, asyncHandler(async (req, res) => { const { paginate, buildPaginatedResponse } = require("../middleware/pagination"); // Parse pagination params const page = parseInt(req.query.page) || 1; const limit = Math.min(parseInt(req.query.limit) || 10, 100); const skip = (page - 1) * limit; const tasks = await Task.find({ completedBy: req.user.id }) .sort({ createdAt: -1 }) .skip(skip) .limit(limit) .populate("street", ["name"]) .populate("completedBy", ["name"]); const totalCount = await Task.countDocuments({ completedBy: req.user.id }); res.json(buildPaginatedResponse(tasks, totalCount, page, limit)); }), ); // Create a task router.post( "/", auth, createTaskValidation, asyncHandler(async (req, res) => { const { street, description } = req.body; const newTask = new Task({ street, description, }); const task = await newTask.save(); res.json(task); }), ); // Complete a task router.put( "/:id", auth, taskIdValidation, asyncHandler(async (req, res) => { const session = await mongoose.startSession(); session.startTransaction(); try { const task = await Task.findById(req.params.id).session(session); if (!task) { await session.abortTransaction(); session.endSession(); return res.status(404).json({ msg: "Task not found" }); } // Check if task is already completed if (task.status === "completed") { await session.abortTransaction(); session.endSession(); return res.status(400).json({ msg: "Task already completed" }); } // Update task task.completedBy = req.user.id; task.status = "completed"; await task.save({ session }); // Update user's completedTasks array const user = await User.findById(req.user.id).session(session); if (!user.completedTasks.includes(task._id)) { user.completedTasks.push(task._id); await user.save({ session }); } // Award points for task completion const { transaction } = await awardTaskCompletionPoints( req.user.id, task._id, session, ); // Check and award badges const newBadges = await checkAndAwardBadges(req.user.id, session); await session.commitTransaction(); session.endSession(); res.json({ task, pointsAwarded: transaction.amount, newBalance: transaction.balanceAfter, badgesEarned: newBadges, }); } catch (err) { await session.abortTransaction(); session.endSession(); throw err; } }), ); module.exports = router;