Align home hero API and CMS hero editor

This commit is contained in:
Tống Thành Đạt
2026-04-09 22:03:00 +07:00
parent 4345b75b03
commit ed09c7fa89
2 changed files with 111 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ const AUDIT_ACTIONS = require("../constants/auditAction");
// Các hàm hỗ trợ
const getHomeDoc = async () => Home.findOne().sort({ updatedAt: -1 });
const getAllHomeDocs = async () => Home.find().sort({ updatedAt: -1 });
const getHomeData = async () => (await getHomeDoc())?.toObject() || {};
const getOrCreateHomeDoc = async () => {
let doc = await getHomeDoc();
@@ -21,6 +22,77 @@ const getOrCreateHomeDoc = async () => {
return doc;
};
const hasMeaningfulValue = (value) =>
typeof value === "string" && value.trim().length > 0;
const getMeaningfulHeroSlides = (hero = {}) => {
if (!Array.isArray(hero.slides)) return [];
return hero.slides.filter((slide = {}) => {
return (
hasMeaningfulValue(slide.title) ||
hasMeaningfulValue(slide.subtitle) ||
hasMeaningfulValue(slide.description) ||
hasMeaningfulValue(slide.heroImage) ||
hasMeaningfulValue(slide.videoUrl) ||
hasMeaningfulValue(slide.primaryButton?.label) ||
hasMeaningfulValue(slide.primaryButton?.href) ||
hasMeaningfulValue(slide.secondaryButton?.label) ||
hasMeaningfulValue(slide.secondaryButton?.href)
);
});
};
const scoreHeroSlides = (slides = []) =>
slides.reduce((score, slide = {}) => {
return (
score +
(slide.title || "").trim().length * 3 +
(slide.subtitle || "").trim().length +
(slide.description || "").trim().length * 2 +
(slide.primaryButton?.label || "").trim().length +
(slide.primaryButton?.href || "").trim().length +
(slide.secondaryButton?.label || "").trim().length +
(slide.secondaryButton?.href || "").trim().length +
(hasMeaningfulValue(slide.heroImage) ? 20 : 0) +
(hasMeaningfulValue(slide.videoUrl) ? 12 : 0)
);
}, 0);
const scoreHeroData = (hero = {}) => {
const slides = getMeaningfulHeroSlides(hero);
if (slides.length > 0) {
return scoreHeroSlides(slides) + slides.length * 30;
}
return (
(hero.title || "").trim().length * 3 +
(hero.subtitle || "").trim().length +
(hero.description || "").trim().length * 2 +
(hero.primaryButton?.label || "").trim().length +
(hero.primaryButton?.href || "").trim().length +
(hero.secondaryButton?.label || "").trim().length +
(hero.secondaryButton?.href || "").trim().length +
(hasMeaningfulValue(hero.heroImage) ? 20 : 0) +
(hasMeaningfulValue(hero.videoUrl) ? 12 : 0)
);
};
const getPreferredHeroData = (docs = []) => {
const heroes = docs
.map((doc) => doc?.hero)
.filter(Boolean);
if (!heroes.length) return {};
return heroes.reduce((bestHero, currentHero) => {
return scoreHeroData(currentHero) > scoreHeroData(bestHero)
? currentHero
: bestHero;
}, heroes[0]);
};
const normalizeStoredImagePath = (imagePath) => {
if (!imagePath || typeof imagePath !== "string") return "";
@@ -373,9 +445,14 @@ exports.apiGetBlogs = async (req, res) => {
};
exports.api = async (req, res) => {
try {
let data = await getHomeData();
const docs = await getAllHomeDocs();
let data = docs[0]?.toObject() || {};
const baseUrl = `${req.protocol}://${req.get("host")}`;
if (docs.length > 1) {
data.hero = getPreferredHeroData(docs.map((doc) => doc.toObject()));
}
// === Xử lý Blog Preview động ===
const blogPreview = data.blogPreview || {};
let blogs = [];