first commit
This commit is contained in:
260
src/controllers/admin/categoryController.js
Normal file
260
src/controllers/admin/categoryController.js
Normal file
@@ -0,0 +1,260 @@
|
||||
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',
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user