261 lines
6.0 KiB
JavaScript
261 lines
6.0 KiB
JavaScript
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',
|
||
});
|
||
}
|
||
};
|