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" }); } };