Spaces:
Running
Running
| const Category = require('../models/categoryModel'); | |
| // Get all categories (optionally filter by parent to get root categories or subcategories) | |
| exports.getAllCategories = async (req, res) => { | |
| try { | |
| const { parentId } = req.query; | |
| // Build filter - if parentId is 'root' or null, get root categories | |
| let filter = {}; | |
| if (parentId === 'root' || parentId === 'null') { | |
| filter.parent = null; | |
| } else if (parentId) { | |
| filter.parent = parentId; | |
| } | |
| const categories = await Category.find(filter) | |
| .populate('parent', 'nameAr nameEn slug') | |
| .lean(); | |
| res.status(200).json({ | |
| status: 'success', | |
| results: categories.length, | |
| data: { | |
| categories, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Get single category with parent and children | |
| exports.getCategory = async (req, res) => { | |
| try { | |
| const category = await Category.findById(req.params.id) | |
| .populate('parent', 'nameAr nameEn slug') | |
| .populate('children', 'nameAr nameEn slug level') | |
| .lean(); | |
| if (!category) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'No category found with that ID', | |
| }); | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { category }, | |
| }); | |
| } catch (err) { | |
| res.status(400).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Create a new category | |
| exports.createCategory = async (req, res) => { | |
| try { | |
| const lastCategory = await Category.findOne().sort({ id: -1 }); | |
| const autoId = lastCategory ? lastCategory.id + 1 : 1; | |
| const newCategory = await Category.create({ | |
| // eslint-disable-next-line node/no-unsupported-features/es-syntax | |
| ...req.body, | |
| id: req.body.id || autoId, | |
| }); | |
| res.status(201).json({ | |
| status: 'success', | |
| data: { category: newCategory }, | |
| }); | |
| } catch (err) { | |
| res.status(400).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Update a category | |
| exports.updateCategory = async (req, res) => { | |
| try { | |
| const updatedCategory = await Category.findByIdAndUpdate( | |
| req.params.id, | |
| req.body, | |
| { new: true, runValidators: true }, | |
| ); | |
| if (!updatedCategory) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'No category found with that ID', | |
| }); | |
| } | |
| res.status(200).json({ | |
| status: 'success', | |
| data: { category: updatedCategory }, | |
| }); | |
| } catch (err) { | |
| res.status(400).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Delete a category | |
| exports.deleteCategory = async (req, res) => { | |
| try { | |
| // First check if category has children | |
| const childrenCount = await Category.countDocuments({ | |
| parent: req.params.id, | |
| }); | |
| if (childrenCount > 0) { | |
| return res.status(400).json({ | |
| status: 'fail', | |
| message: | |
| 'Cannot delete category with subcategories. Delete subcategories first.', | |
| }); | |
| } | |
| const category = await Category.findByIdAndDelete(req.params.id); | |
| if (!category) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'No category found with that ID', | |
| }); | |
| } | |
| res.status(204).json({ | |
| status: 'success', | |
| data: null, | |
| }); | |
| } catch (err) { | |
| res.status(400).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Get all subcategories of a specific category | |
| exports.getSubcategories = async (req, res) => { | |
| try { | |
| const subcategories = await Category.find({ parent: req.params.id }).lean(); | |
| res.status(200).json({ | |
| status: 'success', | |
| results: subcategories.length, | |
| data: { | |
| subcategories, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(400).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |
| // Get full category tree (hierarchical structure) | |
| exports.getCategoryTree = async (req, res) => { | |
| try { | |
| // Fetch all categories once to build tree in memory | |
| const allCategories = await Category.find().lean(); | |
| const categoryMap = {}; | |
| allCategories.forEach((cat) => { | |
| categoryMap[cat._id.toString()] = { ...cat, children: [] }; | |
| }); | |
| const tree = []; | |
| allCategories.forEach((cat) => { | |
| const catObj = categoryMap[cat._id.toString()]; | |
| if (cat.parent) { | |
| const parentId = cat.parent.toString(); | |
| if (categoryMap[parentId]) { | |
| categoryMap[parentId].children.push(catObj); | |
| } | |
| } else { | |
| tree.push(catObj); | |
| } | |
| }); | |
| res.status(200).json({ | |
| status: 'success', | |
| results: tree.length, | |
| data: { | |
| categories: tree, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'fail', | |
| message: err.message, | |
| }); | |
| } | |
| }; | |