forked from UKSOURCE/cms.hailearning.edu.vn
Merge pull request 'feat/huy-05022026-cms-add-footer-api-management' (#23) from feat/huy-05022026-cms-add-footer-api-management into main
Reviewed-on: UKSOURCE/cms.hailearning.edu.vn#23
This commit is contained in:
@@ -1,178 +1,143 @@
|
||||
const { addBaseUrlToImages } = require("../utils/imageHelper");
|
||||
const Footer = require("../models/footer");
|
||||
|
||||
// Get footer data from MongoDB
|
||||
const getFooterData = async () => {
|
||||
const footer = await Footer.findOne({ name: "default" });
|
||||
// GET /api/footer - Public API cho website và CMS load dữ liệu
|
||||
exports.getFooter = async (req, res) => {
|
||||
try {
|
||||
const footer = await Footer.getSingle();
|
||||
const processedData = addBaseUrlToImages(footer.toObject());
|
||||
|
||||
if (!footer) {
|
||||
return {
|
||||
logo: {
|
||||
src: '',
|
||||
alt: ''
|
||||
},
|
||||
about: {
|
||||
title: "About GGC",
|
||||
description: "",
|
||||
mapLink: {
|
||||
text: "Check on google map",
|
||||
url: "",
|
||||
},
|
||||
},
|
||||
address: {
|
||||
text: "",
|
||||
address2: "",
|
||||
mapUrl: "",
|
||||
},
|
||||
contact: {
|
||||
phone: "",
|
||||
hours: "",
|
||||
email: "",
|
||||
},
|
||||
columns: [],
|
||||
social: {
|
||||
links: [],
|
||||
},
|
||||
copyright: {
|
||||
text: "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return footer.toObject();
|
||||
res.json(processedData);
|
||||
} catch (error) {
|
||||
console.error("Error getting footer:", error);
|
||||
res.status(500).json({
|
||||
error: "Failed to get footer data",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// API to get footer data
|
||||
exports.api = async (req, res) => {
|
||||
try {
|
||||
// Lấy footer data
|
||||
const footer = await getFooterData();
|
||||
// PUT /api/admin/footer - Update toàn bộ footer cho CMS
|
||||
exports.updateFooter = async (req, res) => {
|
||||
try {
|
||||
let updateData = req.body;
|
||||
|
||||
// Xử lý URL cho logo và các hình ảnh khác
|
||||
const processedData = addBaseUrlToImages(footer);
|
||||
console.log("=== FOOTER UPDATE REQUEST RECEIVED ===");
|
||||
console.log("Raw body:", JSON.stringify(req.body, null, 2));
|
||||
|
||||
res.json(processedData);
|
||||
} catch (err) {
|
||||
console.error("API Error:", err);
|
||||
res.status(500).json({ error: "Error loading footer data" });
|
||||
}
|
||||
// Nếu có footerJson, parse nó (tương tự Header logic)
|
||||
if (updateData.footerJson && typeof updateData.footerJson === "string") {
|
||||
try {
|
||||
const parsedData = JSON.parse(updateData.footerJson);
|
||||
console.log("✓ Parsed footerJson successfully:", parsedData);
|
||||
updateData = parsedData;
|
||||
} catch (e) {
|
||||
console.error("✗ Error parsing footerJson:", e.message);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "Invalid JSON in footerJson: " + e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Lấy footer hiện tại hoặc tạo mới (giống Header logic)
|
||||
let footer = await Footer.findOne();
|
||||
|
||||
if (!footer) {
|
||||
console.log("No existing footer found, creating new one");
|
||||
footer = new Footer(updateData);
|
||||
await footer.save();
|
||||
console.log("✓ Footer created:", footer._id);
|
||||
} else {
|
||||
console.log("✓ Found existing footer:", footer._id);
|
||||
// Merge với dữ liệu cũ thay vì overwrite (giống Header)
|
||||
Object.assign(footer, updateData);
|
||||
await footer.save();
|
||||
console.log("✓ Footer updated successfully");
|
||||
}
|
||||
|
||||
const processedData = addBaseUrlToImages(footer.toObject());
|
||||
|
||||
console.log("Updated footer data:", JSON.stringify(processedData, null, 2));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: "Footer updated successfully",
|
||||
data: processedData,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("✗ Error updating footer:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: "Failed to update footer: " + error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy toàn bộ footer data
|
||||
exports.getFooterData = async (req, res) => {
|
||||
try {
|
||||
const footerData = await getFooterData();
|
||||
const processed = addBaseUrlToImages(footerData);
|
||||
res.json(processed);
|
||||
} catch (error) {
|
||||
console.error("Error getting footer data:", error);
|
||||
res.status(500).json({ error: "Error loading footer data" });
|
||||
}
|
||||
};
|
||||
|
||||
// Render admin view
|
||||
// Render admin view (giữ lại cho UI hiện tại)
|
||||
exports.index = async (req, res) => {
|
||||
try {
|
||||
const data = await getFooterData();
|
||||
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
|
||||
try {
|
||||
const data = await Footer.getSingle();
|
||||
const processedData = addBaseUrlToImages(data.toObject());
|
||||
|
||||
// Ensure image paths are absolute for admin preview
|
||||
const processedData = addBaseUrlToImages(data);
|
||||
|
||||
res.render("admin/footer/index", {
|
||||
|
||||
title: "Footer Management",
|
||||
data
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error in footer index:", error);
|
||||
req.flash("error_msg", "An error occurred while loading the page");
|
||||
res.redirect("/admin/dashboard");
|
||||
}
|
||||
res.render("admin/footer/index", {
|
||||
title: "Footer Management",
|
||||
data: processedData,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error in footer index:", error);
|
||||
req.flash("error_msg", "An error occurred while loading the page");
|
||||
res.redirect("/admin/dashboard");
|
||||
}
|
||||
};
|
||||
|
||||
// Cập nhật dữ liệu footer
|
||||
// Update method cho form hiện tại (giống Header pattern)
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
let footerData = req.body;
|
||||
if (footerData.footerJson) {
|
||||
try {
|
||||
footerData = JSON.parse(footerData.footerJson);
|
||||
} catch (err) {
|
||||
console.warn('Invalid footerJson payload, falling back to req.body');
|
||||
}
|
||||
try {
|
||||
let updateData = req.body;
|
||||
|
||||
console.log("=== FOOTER FORM UPDATE REQUEST RECEIVED ===");
|
||||
console.log("Raw body:", JSON.stringify(req.body, null, 2));
|
||||
|
||||
// Nếu có footerJson, parse nó (giống Header logic)
|
||||
if (updateData.footerJson && typeof updateData.footerJson === "string") {
|
||||
try {
|
||||
const parsedData = JSON.parse(updateData.footerJson);
|
||||
console.log("✓ Parsed footerJson successfully:", parsedData);
|
||||
updateData = parsedData;
|
||||
} catch (e) {
|
||||
console.error("✗ Error parsing footerJson:", e.message);
|
||||
req.flash("error_msg", "Invalid JSON in footerJson: " + e.message);
|
||||
return res.redirect("/admin/footer");
|
||||
}
|
||||
}
|
||||
|
||||
// Lấy footer hiện tại hoặc tạo mới (giống Header)
|
||||
let footer = await Footer.findOne();
|
||||
|
||||
if (!footer) {
|
||||
console.log("No existing footer found, creating new one");
|
||||
footer = new Footer(updateData);
|
||||
await footer.save();
|
||||
console.log("✓ Footer created:", footer._id);
|
||||
req.flash("success_msg", "Footer created successfully");
|
||||
} else {
|
||||
console.log("✓ Found existing footer:", footer._id);
|
||||
// Merge với dữ liệu cũ (giống Header)
|
||||
Object.assign(footer, updateData);
|
||||
await footer.save();
|
||||
console.log("✓ Footer updated successfully");
|
||||
req.flash("success_msg", "Footer updated successfully");
|
||||
}
|
||||
|
||||
const activeTab = req.body.activeTab || "about";
|
||||
res.redirect(`/admin/footer?activeTab=${activeTab}`);
|
||||
} catch (err) {
|
||||
console.error("✗ Error updating footer:", err);
|
||||
req.flash("error_msg", err.message || "Error updating footer");
|
||||
res.redirect("/admin/footer");
|
||||
}
|
||||
|
||||
// Tìm footer hiện có hoặc tạo mới nếu không tồn tại
|
||||
let footer = await Footer.findOne({ name: "default" });
|
||||
|
||||
if (!footer) {
|
||||
footer = new Footer({
|
||||
name: "default",
|
||||
about: footerData.about || {
|
||||
title: "About GGC",
|
||||
description: "",
|
||||
mapLink: { text: "Check on google map", url: "" },
|
||||
},
|
||||
address: footerData.address || {
|
||||
text: "",
|
||||
address2: "",
|
||||
mapUrl: "",
|
||||
link2: "",
|
||||
},
|
||||
contact: footerData.contact || { phone: "", hours: "", email: "" },
|
||||
columns: Array.isArray(footerData.columns) ? footerData.columns : [],
|
||||
social: footerData.social || { links: [] },
|
||||
copyright: footerData.copyright || { text: "" },
|
||||
});
|
||||
} else {
|
||||
// Cập nhật các trường
|
||||
if (footerData.about) {
|
||||
footer.about = {
|
||||
title: footerData.about.title || footer.about?.title || "About GGC",
|
||||
description: footerData.about.description || footer.about?.description || "",
|
||||
mapLink: {
|
||||
text: footerData.about.mapLink?.text || footer.about?.mapLink?.text || "Check on google map",
|
||||
url: footerData.about.mapLink?.url || footer.about?.mapLink?.url || ""
|
||||
}
|
||||
};
|
||||
}
|
||||
if (footerData.address) {
|
||||
// Đảm bảo address2 tồn tại để tránh undefined trong view/schema
|
||||
footer.address = {
|
||||
...(footer.address?.toObject
|
||||
? footer.address.toObject()
|
||||
: footer.address),
|
||||
...footerData.address,
|
||||
address2:
|
||||
footerData.address.address2 !== undefined
|
||||
? footerData.address.address2
|
||||
: footer.address?.address2 || "",
|
||||
link2:
|
||||
footerData.address.link2 !== undefined
|
||||
? footerData.address.link2
|
||||
: footer.address?.link2 || "",
|
||||
};
|
||||
}
|
||||
if (footerData.contact) footer.contact = footerData.contact;
|
||||
if (Array.isArray(footerData.columns))
|
||||
footer.columns = footerData.columns;
|
||||
if (footerData.social && Array.isArray(footerData.social.links))
|
||||
footer.social = footerData.social;
|
||||
if (footerData.copyright && typeof footerData.copyright.text === "string")
|
||||
footer.copyright = footerData.copyright;
|
||||
}
|
||||
|
||||
await footer.save();
|
||||
|
||||
req.flash("success_msg", "Footer updated successfully");
|
||||
|
||||
// Redirect back to the active tab
|
||||
const activeTab = req.body.activeTab || 'about';
|
||||
res.redirect(`/admin/footer?activeTab=${activeTab}`);
|
||||
} catch (err) {
|
||||
console.error("Error updating footer:", err);
|
||||
req.flash("error_msg", err.message || "Error updating footer");
|
||||
res.redirect("/admin/footer");
|
||||
}
|
||||
};
|
||||
|
||||
// Legacy API endpoints (giữ lại cho tương thích)
|
||||
exports.api = exports.getFooter;
|
||||
exports.getFooterData = exports.getFooter;
|
||||
|
||||
Reference in New Issue
Block a user