Files
eCommerce-backend/src/controllers/admin/categoryController.js
2026-02-19 17:25:38 +05:30

261 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { prisma } = require('../../config/database');
exports.getAllCategories = async (req, res, next) => {
try {
const categories = await prisma.category.findMany({
orderBy: { name: 'asc' },
});
// res.json({ success: true, data: categories });
res.status(200).json({
// statusCode: 200,
status: true,
message: 'Categories fetched successfully',
data: categories,
});
} catch (error) {
next(error);
}
};
exports.createCategory = async (req, res, next) => {
try {
const { name, description, image, parentId, metaTitle, metaDescription } =
req.body;
// Generate slug from name
let slug = name
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '');
// Check if slug already exists with the same parent
const existing = await prisma.category.findFirst({
where: {
slug,
parentId: parentId || null, // Handle both subcategories and root categories
},
});
if (existing) {
// If exists under same parent, append timestamp to make it unique
slug = `${slug}-${Date.now()}`;
}
const category = await prisma.category.create({
data: {
name,
slug,
description,
image,
parentId,
metaTitle,
metaDescription,
},
});
res.status(201).json({
statusCode: 201,
status: true,
message: 'Category created successfully',
data: category,
});
} catch (error) {
// Handle Prisma duplicate error explicitly
if (error.code === 'P2002') {
return res.status(400).json({
statusCode: 400,
status: false,
message: 'Duplicate field value entered',
});
}
next(error);
}
};
exports.updateCategory = async (req, res, next) => {
try {
const { id } = req.params;
const { name, description, image, parentId, metaTitle, metaDescription } =
req.body;
let slug;
if (name) {
slug = name
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '');
}
const category = await prisma.category.update({
where: { id },
data: {
name,
slug,
description,
image,
parentId,
metaTitle,
metaDescription,
},
});
res.json({
status: true,
message: 'Category updated successfully',
data: category,
});
} catch (error) {
next(error);
}
};
exports.deleteCategory = async (req, res, next) => {
try {
const { id } = req.params;
await prisma.category.delete({
where: { id },
});
res.json({
status: true,
message: 'Category deleted successfully',
});
} catch (error) {
next(error);
}
};
exports.toggleCategoryStatus = async (req, res, next) => {
try {
const { id } = req.params;
const { isActive } = req.body;
// 1⃣ Update parent category
const parentCategory = await prisma.category.update({
where: { id },
data: { isActive },
});
// 2⃣ If parent is being deactivated, also deactivate all children recursively
if (!isActive) {
const deactivateChildren = async parentId => {
const children = await prisma.category.findMany({
where: { parentId },
});
for (const child of children) {
await prisma.category.update({
where: { id: child.id },
data: { isActive: false },
});
// Recursive call for nested subcategories
await deactivateChildren(child.id);
}
};
await deactivateChildren(id);
}
res.json({
status: true,
message: `Category ${isActive ? 'activated' : 'deactivated'} successfully`,
data: parentCategory,
});
} catch (error) {
next(error);
}
};
exports.reorderCategories = async (req, res) => {
const { orders } = req.body;
await Promise.all(
orders.map(item =>
prisma.category.update({
where: { id: item.id },
data: { sequence: item.sequence },
})
)
);
res.json({
status: true,
message: 'Category order updated',
});
};
exports.getCategoryHierarchy = async (req, res, next) => {
try {
// 1. Fetch all categories
const categories = await prisma.category.findMany({
orderBy: { name: 'asc' },
});
// 2. Convert array to a lookup map
const lookup = {};
categories.forEach(cat => {
lookup[cat.id] = { ...cat, children: [] };
});
const hierarchy = [];
// 3. Build hierarchical structure
categories.forEach(cat => {
if (cat.parentId) {
lookup[cat.parentId].children.push(lookup[cat.id]);
} else {
hierarchy.push(lookup[cat.id]);
}
});
res.status(200).json({
// statusCode: 200,
status: true,
message: 'Category hierarchy fetched successfully',
data: hierarchy,
});
} catch (error) {
next(error);
}
};
exports.getCategoryById = async (req, res) => {
try {
const { id } = req.params;
if (!id) {
return res.status(400).json({
success: false,
message: 'Category ID is required',
});
}
const category = await prisma.category.findUnique({
where: {
id: id, // ✅ PASS THE ACTUAL STRING VALUE
},
});
if (!category) {
return res.status(404).json({
success: false,
message: 'Category not found',
});
}
return res.status(200).json({
success: true,
message: 'Category details fetched successfully',
data: category,
});
} catch (error) {
console.error('Get category by id error:', error);
return res.status(500).json({
success: false,
message: 'Error fetching category',
});
}
};