File size: 2,882 Bytes
6e13570
 
4c6b1e8
 
 
 
 
 
 
 
 
 
 
 
6e13570
 
 
4c6b1e8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e13570
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
const Course = require("../models/Course");

/**

 * Public course catalogue listing — powers both the homepage "Our

 * Academy" preview and the full Academy page. Supports the category

 * filter, free-text search, and pagination the Academy page needs,

 * since the number of courses is expected to keep growing.

 *

 * Query params (all optional):

 *   category  - one of Course.CATEGORIES, exact match

 *   search    - matched against title/description (case-insensitive)

 *   page      - 1-indexed, default 1

 *   limit     - default 12, capped at 50 to avoid huge unbounded responses

 */
async function listCourses(req, res, next) {
  try {
    const filter = req.user?.role === "admin" ? {} : { isPublished: true };

    if (req.query.category) {
      filter.category = req.query.category;
    }

    if (req.query.search) {
      const escaped = req.query.search.trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const pattern = new RegExp(escaped, "i");
      filter.$or = [{ title: pattern }, { description: pattern }];
    }

    const page = Math.max(1, parseInt(req.query.page, 10) || 1);
    const limit = Math.min(50, Math.max(1, parseInt(req.query.limit, 10) || 12));

    const [courses, total] = await Promise.all([
      Course.find(filter)
        .sort({ createdAt: 1 })
        .skip((page - 1) * limit)
        .limit(limit),
      Course.countDocuments(filter),
    ]);

    res.json({ courses, total, page, pages: Math.max(1, Math.ceil(total / limit)) });
  } catch (err) {
    next(err);
  }
}

async function getCourse(req, res, next) {
  try {
    const course = await Course.findById(req.params.id);
    if (!course) return res.status(404).json({ error: "Course not found." });
    res.json({ course });
  } catch (err) {
    next(err);
  }
}

async function createCourse(req, res, next) {
  try {
    const course = await Course.create(req.body);
    res.status(201).json({ course });
  } catch (err) {
    if (err.code === 11000) return res.status(409).json({ error: "A course with this slug already exists." });
    next(err);
  }
}

async function updateCourse(req, res, next) {
  try {
    const course = await Course.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
      runValidators: true,
    });
    if (!course) return res.status(404).json({ error: "Course not found." });
    res.json({ course });
  } catch (err) {
    next(err);
  }
}

async function deleteCourse(req, res, next) {
  try {
    const course = await Course.findByIdAndUpdate(req.params.id, { isPublished: false }, { new: true });
    if (!course) return res.status(404).json({ error: "Course not found." });
    res.json({ success: true });
  } catch (err) {
    next(err);
  }
}

module.exports = { listCourses, getCourse, createCourse, updateCourse, deleteCourse };