diff --git a/controllers/homeController.js b/controllers/homeController.js index 2040cd9..9b8e2e7 100644 --- a/controllers/homeController.js +++ b/controllers/homeController.js @@ -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 = []; diff --git a/views/admin/home/sections/hero.ejs b/views/admin/home/sections/hero.ejs index 92a0e84..b2c78de 100644 --- a/views/admin/home/sections/hero.ejs +++ b/views/admin/home/sections/hero.ejs @@ -1,21 +1,30 @@
/contact.