first commit

This commit is contained in:
r2xrzh9q2z-lab
2026-02-02 11:07:09 +07:00
commit d1b931d547
286 changed files with 53992 additions and 0 deletions

View File

@@ -0,0 +1,347 @@
const { addBaseUrlToImages } = require('../utils/imageHelper');
const Header = require('../models/header');
const Menu = require('../models/menuHeader');
// Helper function để thêm title và url cho programmes
const addProgrammeDetails = (programmes, menuUrl) => {
return programmes.map(prog => ({
...prog,
title: prog.name,
url: `${menuUrl}${prog.code}/`
}));
};
// Helper function để xử lý menu tree cho API (đơn giản hóa, map menuid thành id)
const processMenuTreeForAPI = (menuTree) => {
return menuTree.map(item => {
const processedItem = {
id: item.menuid, // Map menuid to id for frontend
title: item.title,
url: item.url,
order: item.order,
parent: item.parent || null,
type: item.type,
children: []
};
// Đệ quy cho children
if (item.children && item.children.length > 0) {
processedItem.children = processMenuTreeForAPI(item.children);
}
return processedItem;
});
};
// Helper function để xử lý menu tree và thêm programme details (cho admin)
const processMenuTree = (menuTree) => {
return menuTree.map(item => {
const processedItem = { ...item };
// Nếu có programmes, thêm title và url
if (item.programmes && item.programmes.length > 0) {
processedItem.programmes = addProgrammeDetails(item.programmes, item.url);
}
// Đệ quy cho children
if (item.children && item.children.length > 0) {
processedItem.children = processMenuTree(item.children);
}
return processedItem;
});
};
// Get header data from MongoDB
const getHeaderData = async () => {
const header = await Header.findOne({ name: 'default' });
if (!header) {
return {
topbar: {
contactInfo: {
phone: '',
email: ''
},
links: []
},
mainMenu: [],
logo: ''
};
}
// Convert to plain object to allow modifications
const headerData = header.toObject();
// Lấy menu tree từ collection menuHeader (đơn giản, không có programmes)
try {
const menuTree = await Menu.getMenuTree();
// Xử lý menu tree để map menuid thành id cho frontend
headerData.mainMenu = processMenuTreeForAPI(menuTree);
} catch (error) {
console.error('Error getting menu tree:', error);
headerData.mainMenu = [];
}
return headerData;
};
// API to get header data
exports.api = async (req, res) => {
try {
// Lấy header data
const header = await getHeaderData();
// Xử lý URL cho logo và các hình ảnh khác
const processedData = addBaseUrlToImages(header);
res.json(processedData);
} catch (err) {
console.error('API Error:', err);
res.status(500).json({ error: 'Error loading header data' });
}
};
// API để lấy menu tree cho frontend (public API)
exports.getMenuTreeAPI = async (req, res) => {
try {
const menuTree = await Menu.getMenuTree();
// Xử lý menu tree để map menuid thành id cho frontend
const processedMenuTree = processMenuTreeForAPI(menuTree);
res.json(processedMenuTree);
} catch (error) {
console.error('Error getting menu tree:', error);
res.status(500).json({ error: 'Error loading menu tree' });
}
};
// API để lấy menu tree (cho admin)
exports.getMenuTree = async (req, res) => {
try {
const menuTree = await Menu.getMenuTree();
res.json(menuTree);
} catch (error) {
console.error('Error getting menu tree:', error);
res.status(500).json({ error: 'Error loading menu tree' });
}
};
// API để lấy programmes theo menu ID
exports.getProgrammesByMenuId = async (req, res) => {
try {
const { menuId } = req.params;
const programmes = await Header.getProgrammesByMenuId(menuId);
// Lấy menu item để có URL
const menuItem = await Menu.findOne({ menuid: menuId });
if (menuItem) {
const programmesWithDetails = addProgrammeDetails(programmes, menuItem.url);
res.json(programmesWithDetails);
} else {
res.json(programmes);
}
} catch (error) {
console.error('Error getting programmes by menu ID:', error);
res.status(500).json({ error: 'Error loading programmes' });
}
};
// API để lấy toàn bộ header data
exports.getHeaderData = async (req, res) => {
try {
const headerData = await getHeaderData();
res.json(headerData);
} catch (error) {
console.error('Error getting header data:', error);
res.status(500).json({ error: 'Error loading header data' });
}
};
// API để lấy menu item theo ID
exports.getMenuItem = async (req, res) => {
try {
const { menuId } = req.params;
const Menu = require('../models/menuHeader');
const menuItem = await Menu.findOne({ menuid: menuId });
if (!menuItem) {
return res.status(404).json({ error: 'Menu item not found' });
}
// Nếu là level type và có fetch = true, lấy programmes
if (menuItem.type === 'level' && menuItem.fetch) {
const programmes = await Menu.getProgrammesByMenuId(menuItem.menuid);
menuItem.programmes = addProgrammeDetails(programmes, menuItem.url);
}
res.json(menuItem);
} catch (error) {
console.error('Error getting menu item:', error);
res.status(500).json({ error: 'Error loading menu item' });
}
};
// Render admin view
exports.index = async (req, res) => {
try {
const data = await getHeaderData();
res.render('admin/header/index', {
title: 'Header Management',
data
});
} catch (error) {
console.error('Error in header index:', error);
req.flash('error_msg', 'An error occurred while loading the page');
res.redirect('/admin/dashboard');
}
};
// Update header (chỉ cập nhật topbar và logo)
exports.update = async (req, res) => {
try {
const headerData = req.body;
// Tìm và cập nhật header
const header = await Header.findOne({ name: 'default' });
if (!header) {
req.flash('error_msg', 'Header not found');
return res.redirect('/admin/header');
}
// Cập nhật từng phần
if (headerData.topbarJson) {
header.topbar = JSON.parse(headerData.topbarJson);
}
if (headerData.logo) {
header.logo = headerData.logo;
}
header.updatedAt = new Date();
await header.save();
// Process menu updates if any
let menuUpdateCount = 0;
let menuErrorCount = 0;
if (headerData.menuUpdates) {
try {
const updates = JSON.parse(headerData.menuUpdates);
if (Array.isArray(updates) && updates.length > 0) {
const Menu = require('../models/menuHeader');
for (const update of updates) {
try {
const { menuid, title, order, type, parent, fetch, isActive } = update;
const updateData = {
title: title,
order: order,
type: type,
parent: parent
};
// Add fetch field if provided
if (fetch !== undefined) {
updateData.fetch = fetch;
}
// Add isActive field if provided
if (isActive !== undefined) {
updateData.isActive = isActive;
}
const result = await Menu.findOneAndUpdate(
{ menuid: menuid },
updateData,
{ new: true }
);
if (result) {
menuUpdateCount++;
} else {
console.warn(`Menu item not found for update: ${menuid}`);
menuErrorCount++;
}
} catch (innerErr) {
console.error(`Error updating menu item ${update.menuid}:`, innerErr);
menuErrorCount++;
}
}
}
} catch (err) {
console.error('Error processing menu updates:', err);
}
}
let flashMsg = 'Header updated successfully.';
if (menuUpdateCount > 0) {
flashMsg += ` Updated ${menuUpdateCount} menu items.`;
}
if (menuErrorCount > 0) {
req.flash('error_msg', `Updated ${menuUpdateCount} items, but failed to update ${menuErrorCount} items. Check logs.`);
} else {
req.flash('success_msg', flashMsg);
}
// Redirect back to the active tab
const activeTab = req.body.activeTab || 'topbar';
res.redirect(`/admin/header?activeTab=${activeTab}`);
} catch (error) {
console.error('Error updating header:', error);
req.flash('error_msg', 'Error updating header: ' + error.message);
res.redirect('/admin/header');
}
};
// Update menu structure (order and parent)
exports.updateMenu = async (req, res) => {
try {
const { updates } = req.body;
if (!updates || !Array.isArray(updates)) {
return res.status(400).json({
success: false,
error: 'Invalid updates data'
});
}
const Menu = require('../models/menuHeader');
// Update each menu item
for (const update of updates) {
const { menuid, title, order, type, parent, fetch, isActive } = update;
console.log(menuid, title, order, type, parent, fetch, isActive);
const updateData = {
title: title,
order: order,
type: type,
parent: parent
};
// Add fetch field if provided (for level type menus)
if (fetch !== undefined) {
updateData.fetch = fetch;
}
// Add isActive field if provided
if (isActive !== undefined) {
updateData.isActive = isActive;
}
await Menu.findOneAndUpdate(
{ menuid: menuid },
updateData,
{ new: true }
);
}
res.json({ success: true });
} catch (error) {
console.error('Error updating menu structure:', error);
req.flash('error_msg', 'Error updating menu structure: ' + error.message);
res.redirect('/admin/header');
}
};