Files

163 lines
4.6 KiB
JavaScript

const About = require("../models/about");
const { addBaseUrlToImages } = require("../utils/imageHelper");
// Helpers
const getAboutDoc = async () => About.findOne().sort({ updatedAt: -1 });
const getAboutData = async () => (await getAboutDoc())?.toObject() || {};
const getDefaultAboutData = () => ({
hero: {
badge: "",
title: "",
description: "",
studentCount: "",
image: "",
imageAlt: "",
coreValues: [],
},
leadership: {
heading: "",
description: "",
members: [],
},
learningModel: {
heading: "",
description: "",
async: {
title: "",
description: "",
features: [],
},
sync: {
title: "",
description: "",
features: [],
},
},
accreditation: {
heading: "",
description: "",
badges: [],
stats: [],
},
successStories: {
heading: "",
description: "",
stories: [],
},
cta: {
heading: "",
description: "",
primaryButton: { label: "", href: "" },
secondaryButton: { label: "", href: "" },
},
});
// Admin: render management view with data from MongoDB
exports.index = async (req, res) => {
try {
let data = await getAboutData();
const defaults = getDefaultAboutData();
// Merge defaults for any missing sections
const sections = Object.keys(defaults);
sections.forEach((s) => {
data[s] = data[s] || defaults[s];
});
const frontendUrl = process.env.FRONTEND_URL || "";
return res.render("admin/about/index", {
layout: "layouts/main",
title: "About Management",
data,
frontendUrl,
currentPath: req.path,
user: req.session.user,
});
} catch (err) {
console.error("About index error:", err);
req.flash("error_msg", "Error loading about data");
return req.session.save(() => res.redirect("/admin/dashboard"));
}
};
// Admin: parse req.body sections and save to MongoDB
exports.update = async (req, res) => {
try {
const sections = [
"hero",
"leadership",
"learningModel",
"accreditation",
"successStories",
"cta",
];
let doc = await getAboutDoc();
if (!doc) {
doc = new About({});
}
let hasChanges = false;
for (const section of sections) {
if (req.body[section]) {
try {
const payload = JSON.parse(req.body[section]);
doc[section] = payload;
doc.markModified(section);
hasChanges = true;
} catch (e) {
console.error(`Invalid JSON for ${section}:`, e);
}
}
}
if (!hasChanges) {
req.flash("info_msg", "No changes were made");
return req.session.save(() => res.redirect("/admin/about"));
}
await doc.save();
req.flash("success_msg", "About page configuration has been updated!");
return req.session.save(() => res.redirect("/admin/about"));
} catch (err) {
console.error("About update error:", err);
req.flash("error_msg", `Update error: ${err.message}`);
return req.session.save(() => res.redirect("/admin/about"));
}
};
// Recursively prepend BACKEND_URL to any relative /uploads/... paths in an object
function resolveImageUrls(obj, baseUrl) {
if (!obj || typeof obj !== "object") return obj;
if (Array.isArray(obj)) return obj.map((item) => resolveImageUrls(item, baseUrl));
const result = {};
for (const [key, val] of Object.entries(obj)) {
if (typeof val === "string" && val.startsWith("/uploads/")) {
result[key] = `${baseUrl}${val}`;
} else {
result[key] = resolveImageUrls(val, baseUrl);
}
}
return result;
}
// Public API: return JSON data for frontend
exports.api = async (req, res) => {
try {
let data = await getAboutData();
if (!data || Object.keys(data).length === 0) {
data = getDefaultAboutData();
}
const baseUrl = process.env.BACKEND_URL || `${req.protocol}://${req.get("host")}`;
return res.json(resolveImageUrls(data, baseUrl));
} catch (err) {
console.error("About API error:", err);
return res.status(500).json({ error: "Error loading about data" });
}
};