Files
cms.techvanguard.vn/controllers/studentSupportController.js

187 lines
5.3 KiB
JavaScript

const { addBaseUrlToImages } = require("../utils/imageHelper");
const { normalizeIconClass } = require("../utils/iconOptions");
const StudentSupport = require("../models/studentSupport");
const writeAuditLog = require("../audit/writeAuditLog");
const diffObject = require("../audit/diffObject");
const AUDIT_ACTIONS = require("../constants/auditAction");
const SLUG = "student-support";
function emptyPageShape() {
return {
metadata: { title: "", description: "" },
hero: {
badge: "",
title: "",
description: "",
primaryButton: { label: "", href: "" },
secondaryButton: { label: "", href: "" },
image: "",
imageAlt: "",
},
directory: { title: "", subtitle: "", services: [] },
contactSection: {
heading: "",
description: "",
channels: [],
form: {
heading: "",
fields: {
firstName: { label: "", placeholder: "" },
lastName: { label: "", placeholder: "" },
studentId: { label: "", placeholder: "" },
department: { label: "" },
message: { label: "", placeholder: "" },
},
departments: [],
submitLabel: "",
successMessage: "",
},
},
};
}
function parseJsonField(raw) {
if (raw == null || raw === "") return null;
if (typeof raw === "object") return raw;
try {
return JSON.parse(raw);
} catch {
return null;
}
}
/** Chuẩn hoá mọi field icon theo whitelist (dropdown admin). */
function sanitizeIcons(payload) {
if (!payload) return payload;
if (payload.hero) {
/* hero không có icon list */
}
if (payload.directory?.services?.length) {
payload.directory.services = payload.directory.services.map((s) => ({
...s,
icon: normalizeIconClass(s.icon),
hoursIcon: normalizeIconClass(s.hoursIcon),
}));
}
if (payload.contactSection?.channels?.length) {
payload.contactSection.channels = payload.contactSection.channels.map((c) => ({
...c,
icon: normalizeIconClass(c.icon),
}));
}
return payload;
}
async function getDocument() {
return StudentSupport.findOne({ slug: SLUG }).lean();
}
/**
* GET /api/student-support — public payload giống file JSON frontend (không kèm _id/slug).
*/
exports.api = async (req, res) => {
try {
const doc = await getDocument();
if (!doc) {
return res.status(404).json({ error: "Student Support content not found" });
}
const baseUrl =
process.env.BACKEND_URL ?? `${req.protocol}://${req.get("host")}`;
const body = {
metadata: doc.metadata || {},
hero: doc.hero || {},
directory: doc.directory || { services: [] },
contactSection: doc.contactSection || {},
};
res.json(addBaseUrlToImages(body, baseUrl));
} catch (err) {
console.error("studentSupport.api:", err);
res.status(500).json({ error: "Error loading Student Support data" });
}
};
exports.index = async (req, res) => {
try {
const doc = await getDocument();
const data = doc
? {
metadata: doc.metadata || {},
hero: doc.hero || {},
directory: doc.directory || { services: [] },
contactSection: doc.contactSection || {},
}
: emptyPageShape();
const { ICON_OPTIONS } = require("../utils/iconOptions");
const frontendUrl = process.env.FRONTEND_URL || "";
res.render("admin/student-support/index", {
title: "Student Support",
layout: "layouts/main",
data,
iconOptions: ICON_OPTIONS,
frontendUrl,
currentPath: req.path,
user: req.session.user,
});
} catch (error) {
console.error("studentSupport.index:", error);
req.flash("error_msg", "Could not load Student Support page");
res.redirect("/admin/dashboard");
}
};
exports.update = async (req, res) => {
try {
const metadata = parseJsonField(req.body.metadata);
const hero = parseJsonField(req.body.hero);
const directory = parseJsonField(req.body.directory);
const contactSection = parseJsonField(req.body.contactSection);
if (!metadata || !hero || !directory || !contactSection) {
req.flash("error_msg", "Invalid form payload. Please try again.");
return res.redirect("/admin/student-support");
}
const payload = sanitizeIcons({
metadata,
hero,
directory,
contactSection,
});
let doc = await StudentSupport.findOne({ slug: SLUG });
const beforeData = doc ? JSON.parse(JSON.stringify(doc.toObject())) : {};
if (!doc) {
doc = new StudentSupport({ slug: SLUG, ...payload });
} else {
doc.set(payload);
}
await doc.save();
const afterData = JSON.parse(JSON.stringify(doc.toObject()));
const changes = diffObject(beforeData, afterData);
if (changes.length > 0) {
await writeAuditLog({
model: "StudentSupport",
documentId: doc._id,
action: AUDIT_ACTIONS.UPDATE_STUDENT_SUPPORT,
before: beforeData,
after: afterData,
changes,
req,
});
}
req.flash("success_msg", "Student Support updated successfully");
res.redirect("/admin/student-support");
} catch (err) {
console.error("studentSupport.update:", err);
req.flash("error_msg", err.message || "Error updating Student Support");
res.redirect("/admin/student-support");
}
};