GIF89a
import AsyncHandler from '../../utils/AsyncHandler.js'
import ApiError from '../../utils/ApiErrorHandler.js'
import Category from '../../models/category.model.js'
import { fileDelete } from '../../utils/FileDelete.js'
import ApiResponse from '../../utils/ApiRespinseHandler.js'
import mongoose from 'mongoose'
import path from 'path'
// ============================================================
// POST /api/v1/category (admin only)
// ============================================================
export const createCategory = AsyncHandler(async (req, res) => {
const { catName, description, position, slug } = req.body;
if (!catName) {
fileDelete(req.file?.path);
throw new ApiError(400, 'Category name is required');
}
const isDuplicate = await Category.findOne({ catName: catName.trim() });
if (isDuplicate) {
fileDelete(req.file?.path);
throw new ApiError(409, 'Category already exists');
}
let imagePath = '';
if (req.file?.path) {
imagePath = `uploads/${path.basename(req.file.path)}`;
}
const autoSlug = slug
? slug.toLowerCase().trim().replace(/\s+/g, '-')
: catName.toLowerCase().trim().replace(/\s+/g, '-');
const newCategory = await Category.create({
catName: catName.trim(),
description,
position: position ? Number(position) : 0,
slug: autoSlug,
image: imagePath,
createdBy: req.userId
});
return res.status(201).json(
new ApiResponse(201, 'Category created successfully', newCategory)
);
});
// ============================================================
// PATCH /api/v1/category/:catId (admin only)
// ============================================================
export const updateCategory = AsyncHandler(async (req, res) => {
const { catId } = req.params;
const { catName, description, position, slug, status } = req.body;
if (!mongoose.Types.ObjectId.isValid(catId)) {
fileDelete(req.file?.path);
throw new ApiError(400, 'Invalid category ID');
}
const category = await Category.findById(catId);
if (!category) {
fileDelete(req.file?.path);
throw new ApiError(404, 'Category not found');
}
// Only update image if a new file was actually uploaded
if (req.file?.path) {
category.image = `uploads/${path.basename(req.file.path)}`;
}
if (catName !== undefined) category.catName = catName.trim();
if (description !== undefined) category.description = description;
if (position !== undefined) category.position = Number(position);
if (status !== undefined) category.status = status === true || status === 'true';
if (slug !== undefined) {
category.slug = slug.toLowerCase().trim().replace(/\s+/g, '-');
}
await category.save();
return res.status(200).json(
new ApiResponse(200, 'Category updated successfully', category)
);
});
// ============================================================
// DELETE /api/v1/category/:catId (admin only)
// ============================================================
export const deleteCategory = AsyncHandler(async (req, res) => {
const { catId } = req.params;
if (!mongoose.Types.ObjectId.isValid(catId)) {
throw new ApiError(400, 'Invalid category ID');
}
const category = await Category.findByIdAndDelete(catId);
if (!category) {
throw new ApiError(404, 'Category not found');
}
return res.status(200).json(
new ApiResponse(200, 'Category deleted successfully', { _id: catId })
);
});
// ============================================================
// GET /api/v1/category (public)
// Query: ?catId= for single, otherwise all
// ============================================================
export const getCategory = AsyncHandler(async (req, res) => {
const queryObj = {};
if (req.query.catId) {
if (!mongoose.Types.ObjectId.isValid(req.query.catId)) {
throw new ApiError(400, 'Invalid category ID format');
}
queryObj._id = req.query.catId;
}
const categories = await Category.find(queryObj).sort({ position: 1, createdAt: -1 });
return res.status(200).json(
new ApiResponse(200, 'Categories fetched successfully', categories)
);
});