forked from UKSOURCE/cms.hailearning.edu.vn
342 lines
9.1 KiB
JavaScript
342 lines
9.1 KiB
JavaScript
const BlogCategory = require('../models/blogCategory');
|
|
const slugify = require('slugify');
|
|
|
|
// -------------------- Admin Controllers --------------------
|
|
|
|
// Display category management page
|
|
exports.index = async (req, res) => {
|
|
try {
|
|
const categories = await BlogCategory.find()
|
|
.sort({ name: 1 })
|
|
.lean();
|
|
|
|
res.render('admin/blog/categories/index', {
|
|
layout: 'layouts/main',
|
|
title: 'Blog Categories',
|
|
categories,
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error('Category index error:', err);
|
|
req.flash('error_msg', 'Error loading categories');
|
|
res.redirect('/admin/dashboard');
|
|
}
|
|
};
|
|
|
|
// Show create category form
|
|
exports.create = async (req, res) => {
|
|
try {
|
|
res.render('admin/blog/categories/create', {
|
|
layout: 'layouts/main',
|
|
title: 'Create New Category',
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error('Category create form error:', err);
|
|
req.flash('error_msg', 'Error loading create form');
|
|
res.redirect('/admin/blog/categories');
|
|
}
|
|
};
|
|
|
|
// Store new category
|
|
exports.store = async (req, res) => {
|
|
try {
|
|
const {
|
|
name,
|
|
description,
|
|
isActive
|
|
} = req.body;
|
|
|
|
// Generate slug
|
|
const slug = slugify(name, {
|
|
lower: true,
|
|
strict: true,
|
|
locale: 'vi'
|
|
});
|
|
|
|
// Check if slug exists
|
|
const existingCategory = await BlogCategory.findOne({ slug });
|
|
if (existingCategory) {
|
|
req.flash('error_msg', 'A category with this name already exists');
|
|
return res.redirect('/admin/blog/categories/create');
|
|
}
|
|
|
|
// Create category data
|
|
const categoryData = {
|
|
name,
|
|
slug,
|
|
description,
|
|
isActive: isActive === 'on'
|
|
};
|
|
|
|
// Create category
|
|
const category = new BlogCategory(categoryData);
|
|
await category.save();
|
|
|
|
req.flash('success_msg', 'Category created successfully');
|
|
res.redirect('/admin/blog/categories');
|
|
} catch (err) {
|
|
console.error('Category store error:', err);
|
|
req.flash('error_msg', 'Error creating category');
|
|
res.redirect('/admin/blog/categories/create');
|
|
}
|
|
};
|
|
|
|
// Show edit category form
|
|
exports.edit = async (req, res) => {
|
|
try {
|
|
const category = await BlogCategory.findById(req.params.id);
|
|
|
|
if (!category) {
|
|
req.flash('error_msg', 'Category not found');
|
|
return res.redirect('/admin/blog/categories');
|
|
}
|
|
|
|
res.render('admin/blog/categories/edit', {
|
|
layout: 'layouts/main',
|
|
title: 'Edit Category',
|
|
category,
|
|
currentPath: req.path,
|
|
user: req.session.user
|
|
});
|
|
} catch (err) {
|
|
console.error('Category edit form error:', err);
|
|
req.flash('error_msg', 'Error loading category');
|
|
res.redirect('/admin/blog/categories');
|
|
}
|
|
};
|
|
|
|
// Update category
|
|
exports.update = async (req, res) => {
|
|
try {
|
|
const category = await BlogCategory.findById(req.params.id);
|
|
|
|
if (!category) {
|
|
req.flash('error_msg', 'Category not found');
|
|
return res.redirect('/admin/blog/categories');
|
|
}
|
|
|
|
const {
|
|
name,
|
|
description,
|
|
isActive
|
|
} = req.body;
|
|
|
|
// Update category data
|
|
category.name = name;
|
|
category.description = description;
|
|
category.isActive = isActive === 'on';
|
|
|
|
// Generate new slug if name changed
|
|
const newSlug = slugify(name, {
|
|
lower: true,
|
|
strict: true,
|
|
locale: 'vi'
|
|
});
|
|
|
|
if (newSlug !== category.slug) {
|
|
const existingCategory = await BlogCategory.findOne({
|
|
slug: newSlug,
|
|
_id: { $ne: category._id }
|
|
});
|
|
if (existingCategory) {
|
|
req.flash('error_msg', 'A category with this name already exists');
|
|
return res.redirect(`/admin/blog/categories/${category._id}/edit`);
|
|
}
|
|
category.slug = newSlug;
|
|
}
|
|
|
|
await category.save();
|
|
|
|
req.flash('success_msg', 'Category updated successfully');
|
|
res.redirect('/admin/blog/categories');
|
|
} catch (err) {
|
|
console.error('Category update error:', err);
|
|
req.flash('error_msg', 'Error updating category');
|
|
res.redirect(`/admin/blog/categories/${req.params.id}/edit`);
|
|
}
|
|
};
|
|
|
|
// Delete category
|
|
exports.destroy = async (req, res) => {
|
|
try {
|
|
const category = await BlogCategory.findById(req.params.id);
|
|
|
|
if (!category) {
|
|
// Check if it's an AJAX request
|
|
const isAjax = req.xhr || req.headers['accept']?.includes('application/json') || req.headers['content-type']?.includes('application/json');
|
|
if (isAjax) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Category not found'
|
|
});
|
|
}
|
|
req.flash('error_msg', 'Category not found');
|
|
return res.redirect('/admin/blog/categories');
|
|
}
|
|
|
|
// Check if category has posts
|
|
const Blog = require('../models/blog');
|
|
const postCount = await Blog.countDocuments({ category: { $in: [category.name] } });
|
|
|
|
if (postCount > 0) {
|
|
// Check if it's an AJAX request
|
|
const isAjax = req.xhr || req.headers['accept']?.includes('application/json') || req.headers['content-type']?.includes('application/json');
|
|
if (isAjax) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Cannot delete category that has blog posts'
|
|
});
|
|
}
|
|
req.flash('error_msg', 'Cannot delete category that has blog posts');
|
|
return res.redirect('/admin/blog/categories');
|
|
}
|
|
|
|
await BlogCategory.findByIdAndDelete(req.params.id);
|
|
|
|
// Check if it's an AJAX request
|
|
const isAjax = req.xhr || req.headers['accept']?.includes('application/json') || req.headers['content-type']?.includes('application/json');
|
|
if (isAjax) {
|
|
return res.json({
|
|
success: true,
|
|
message: 'Category deleted successfully'
|
|
});
|
|
}
|
|
|
|
req.flash('success_msg', 'Category deleted successfully');
|
|
res.redirect('/admin/blog/categories');
|
|
} catch (err) {
|
|
console.error('Category delete error:', err);
|
|
|
|
// Check if it's an AJAX request
|
|
const isAjax = req.xhr || req.headers['accept']?.includes('application/json') || req.headers['content-type']?.includes('application/json');
|
|
if (isAjax) {
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: 'Error deleting category',
|
|
error: err.message || 'Error deleting category'
|
|
});
|
|
}
|
|
|
|
req.flash('error_msg', 'Error deleting category');
|
|
res.redirect('/admin/blog/categories');
|
|
}
|
|
};
|
|
|
|
// -------------------- Public API Controllers --------------------
|
|
|
|
// Get all active categories
|
|
exports.api = async (req, res) => {
|
|
try {
|
|
const categories = await BlogCategory.getActive();
|
|
|
|
// Update post counts
|
|
for (const category of categories) {
|
|
await category.updatePostCount();
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Categories fetched successfully',
|
|
data: categories
|
|
});
|
|
} catch (err) {
|
|
console.error('Categories API error:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Error loading categories',
|
|
error: err.message || 'Error loading categories'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Get category by slug
|
|
exports.apiShow = async (req, res) => {
|
|
try {
|
|
const category = await BlogCategory.findOne({
|
|
slug: req.params.slug,
|
|
isActive: true
|
|
}).lean();
|
|
|
|
if (!category) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Category not found'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Category fetched successfully',
|
|
data: category
|
|
});
|
|
} catch (err) {
|
|
console.error('Category show API error:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Error loading category',
|
|
error: err.message || 'Error loading category'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Quick create category (for inline creation in blog form)
|
|
exports.quickCreate = async (req, res) => {
|
|
try {
|
|
const { name, description } = req.body;
|
|
|
|
if (!name || !name.trim()) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Category name is required'
|
|
});
|
|
}
|
|
|
|
const categoryName = name.trim();
|
|
|
|
// Generate slug
|
|
const slug = slugify(categoryName, {
|
|
lower: true,
|
|
strict: true,
|
|
locale: 'vi'
|
|
});
|
|
|
|
// Check if category already exists
|
|
let category = await BlogCategory.findOne({ slug });
|
|
|
|
if (category) {
|
|
return res.json({
|
|
success: true,
|
|
message: 'Category already exists',
|
|
data: category.toObject()
|
|
});
|
|
}
|
|
|
|
// Create new category
|
|
category = new BlogCategory({
|
|
name: categoryName,
|
|
slug,
|
|
description: description || '',
|
|
isActive: true
|
|
});
|
|
|
|
await category.save();
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Category created successfully',
|
|
data: category.toObject()
|
|
});
|
|
} catch (err) {
|
|
console.error('Quick create category error:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Error creating category',
|
|
error: err.message || 'Error creating category'
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = exports; |