From e7929568dc1a08c8a1998389fb1b2e86df0d5880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Minh=20Nh=E1=BA=ADt?= Date: Sat, 11 Apr 2026 04:46:33 +0700 Subject: [PATCH] fix: on/off tab in home page --- .env.example | Bin 616 -> 686 bytes controllers/homeController.js | 9 +++----- models/home.js | 3 +++ scripts/cleanup-home-docs.js | 22 ++++++++++++++++++++ views/admin/home/sections/achievements.ejs | 4 ++-- views/admin/home/sections/blogPreview.ejs | 4 ++-- views/admin/home/sections/faq.ejs | 4 ++-- views/admin/home/sections/hero.ejs | 4 ++-- views/admin/home/sections/partners.ejs | 4 ++-- views/admin/home/sections/testimonials.ejs | 4 ++-- views/admin/home/sections/videoGallery.ejs | 4 ++-- views/admin/home/sections/visaCountries.ejs | 4 ++-- views/admin/home/sections/visaSolutions.ejs | 4 ++-- views/admin/home/sections/whyChooseUs.ejs | 4 ++-- 14 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 scripts/cleanup-home-docs.js diff --git a/.env.example b/.env.example index 6e9969b5d10bccc452cb2dae3cb5f057b31e2d94..797edcba66245019435729c4e6a583f87cbbe45a 100644 GIT binary patch delta 233 zcmYk0K@P!S5QV=AaRUo`Hl+U6f=HS!tl5+U2tpH7+OoB90n&SLElWr6{&pji_a^Vn zo6LObug0VGG~c3MYd41&l~*jC&Yw2L+qvI7d`7sMSMZpWj`H#cglvdO*|H{QO2SE1 zskl^u{FIBlE}1yxT5=>l2zIYZF4T{55~XuyL2!kzy0fQa_PZa)aTFhX@pbvz}47m)&K* E09I-v%>V!Z diff --git a/controllers/homeController.js b/controllers/homeController.js index 043f51c..5f8bc22 100644 --- a/controllers/homeController.js +++ b/controllers/homeController.js @@ -445,14 +445,11 @@ exports.apiGetBlogs = async (req, res) => { }; exports.api = async (req, res) => { try { - const docs = await getAllHomeDocs(); - let data = docs[0]?.toObject() || {}; + // Chỉ dùng doc mới nhất, không merge nhiều docs + const doc = await getHomeDoc(); + let data = doc?.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/models/home.js b/models/home.js index 57fd0b0..6c310b6 100644 --- a/models/home.js +++ b/models/home.js @@ -349,5 +349,8 @@ const HomeSchema = new Schema( }, ); +// Đảm bảo chỉ có 1 document duy nhất (singleton pattern) +HomeSchema.index({ createdAt: 1 }, { unique: false }); + module.exports = mongoose.model("Home", HomeSchema); diff --git a/scripts/cleanup-home-docs.js b/scripts/cleanup-home-docs.js new file mode 100644 index 0000000..b341f6a --- /dev/null +++ b/scripts/cleanup-home-docs.js @@ -0,0 +1,22 @@ +require('dotenv').config(); +const mongoose = require('mongoose'); +const Home = require('../models/home'); + +mongoose.connect(process.env.MONGODB_URI).then(async () => { + const docs = await Home.find().sort({ updatedAt: -1 }).lean(); + console.log('Total docs:', docs.length); + + if (docs.length <= 1) { + console.log('Nothing to clean up.'); + return; + } + + const keep = docs[0]; + const idsToDelete = docs.slice(1).map(d => d._id); + await Home.deleteMany({ _id: { $in: idsToDelete } }); + + console.log('Kept doc:', keep._id, '| hero.enabled:', keep.hero?.enabled); + console.log('Deleted', idsToDelete.length, 'duplicate docs'); + + await mongoose.disconnect(); +}); diff --git a/views/admin/home/sections/achievements.ejs b/views/admin/home/sections/achievements.ejs index 95b1942..c2c836c 100644 --- a/views/admin/home/sections/achievements.ejs +++ b/views/admin/home/sections/achievements.ejs @@ -1,4 +1,4 @@ - +
@@ -88,7 +88,7 @@ window.homeScrapers.achievements = function () { const items = []; - const enabled = document.getElementById("achievementEnabled")?.checked !== false; + const enabled = document.getElementById("achievementEnabled")?.checked === true; document.querySelectorAll('.achievement-item').forEach(el => { items.push({ diff --git a/views/admin/home/sections/blogPreview.ejs b/views/admin/home/sections/blogPreview.ejs index 2c73f72..9a32d2b 100644 --- a/views/admin/home/sections/blogPreview.ejs +++ b/views/admin/home/sections/blogPreview.ejs @@ -1,4 +1,4 @@ - +
@@ -158,7 +158,7 @@ window.homeScrapers.blogPreview = () => { const selectedIds = []; - const enabled = document.getElementById("blogpreviewEnabled")?.checked !== false; + const enabled = document.getElementById("blogpreviewEnabled")?.checked === true; document.querySelectorAll('.blog-checkbox:checked').forEach(cb => { selectedIds.push(cb.value); diff --git a/views/admin/home/sections/faq.ejs b/views/admin/home/sections/faq.ejs index 73655ba..849bab5 100644 --- a/views/admin/home/sections/faq.ejs +++ b/views/admin/home/sections/faq.ejs @@ -1,4 +1,4 @@ - +
@@ -139,7 +139,7 @@ window.homeScrapers.faq = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById('faqEnabled')?.checked !== false; + const enabled = document.getElementById('faqEnabled')?.checked === true; const items = []; document.querySelectorAll(".faq-item").forEach((el, idx) => { diff --git a/views/admin/home/sections/hero.ejs b/views/admin/home/sections/hero.ejs index da755d9..21cdd35 100644 --- a/views/admin/home/sections/hero.ejs +++ b/views/admin/home/sections/hero.ejs @@ -1,4 +1,4 @@ - +
@@ -203,7 +203,7 @@ const getVal = (id) => (document.getElementById(id)?.value || "").trim(); const backgroundImage = getVal("heroBackgroundImage"); - const enabled = document.getElementById("heroEnabled")?.checked !== false; + const enabled = document.getElementById("heroEnabled")?.checked === true; const slides = []; const slideEls = document.querySelectorAll(".hero-slide-item"); diff --git a/views/admin/home/sections/partners.ejs b/views/admin/home/sections/partners.ejs index c340f81..3223ce1 100644 --- a/views/admin/home/sections/partners.ejs +++ b/views/admin/home/sections/partners.ejs @@ -1,4 +1,4 @@ - +
@@ -120,7 +120,7 @@ window.homeScrapers.partners = function () { const visaItems = []; - const enabled = document.getElementById('partnersEnabled')?.checked !== false; + const enabled = document.getElementById('partnersEnabled')?.checked === true; document.querySelectorAll('.visa-item').forEach(el => { visaItems.push({ diff --git a/views/admin/home/sections/testimonials.ejs b/views/admin/home/sections/testimonials.ejs index 26b6fca..6033226 100644 --- a/views/admin/home/sections/testimonials.ejs +++ b/views/admin/home/sections/testimonials.ejs @@ -1,4 +1,4 @@ - +
@@ -135,7 +135,7 @@ window.homeScrapers.testimonials = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById("testimonialEnabled")?.checked !== false; + const enabled = document.getElementById("testimonialEnabled")?.checked === true; const items = []; document.querySelectorAll(".testimonial-item").forEach((el, idx) => { diff --git a/views/admin/home/sections/videoGallery.ejs b/views/admin/home/sections/videoGallery.ejs index 32cf2df..a3eae6d 100644 --- a/views/admin/home/sections/videoGallery.ejs +++ b/views/admin/home/sections/videoGallery.ejs @@ -1,4 +1,4 @@ - +
@@ -64,7 +64,7 @@ window.homeScrapers.videoGallery = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById("videoGalleryEnabled")?.checked !== false; + const enabled = document.getElementById("videoGalleryEnabled")?.checked === true; return { heading: getVal("videoGalleryHeading"), videoUrl: getVal("videoGalleryVideoUrl"), diff --git a/views/admin/home/sections/visaCountries.ejs b/views/admin/home/sections/visaCountries.ejs index da1bc52..10c3f0c 100644 --- a/views/admin/home/sections/visaCountries.ejs +++ b/views/admin/home/sections/visaCountries.ejs @@ -1,4 +1,4 @@ - +
@@ -135,7 +135,7 @@ window.homeScrapers.visaCountries = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById("visaCountriesEnabled")?.checked !== false + const enabled = document.getElementById("visaCountriesEnabled")?.checked === true const visaTypesRaw = getVal("visaCountriesVisaTypes_0"); const visaTypes = visaTypesRaw ? visaTypesRaw.split(",").map((s) => s.trim()).filter(Boolean) : []; diff --git a/views/admin/home/sections/visaSolutions.ejs b/views/admin/home/sections/visaSolutions.ejs index 0f857f5..706b144 100644 --- a/views/admin/home/sections/visaSolutions.ejs +++ b/views/admin/home/sections/visaSolutions.ejs @@ -1,4 +1,4 @@ - +
@@ -100,7 +100,7 @@ window.homeScrapers.visaSolutions = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById("visaSolutionsEnabled")?.checked !== false; + const enabled = document.getElementById("visaSolutionsEnabled")?.checked === true; const items = []; document.querySelectorAll(".visa-solution-item").forEach((el, idx) => { diff --git a/views/admin/home/sections/whyChooseUs.ejs b/views/admin/home/sections/whyChooseUs.ejs index 93cbed2..55decf4 100644 --- a/views/admin/home/sections/whyChooseUs.ejs +++ b/views/admin/home/sections/whyChooseUs.ejs @@ -1,4 +1,4 @@ - +
@@ -206,7 +206,7 @@ window.homeScrapers = window.homeScrapers || {}; window.homeScrapers.whyChooseUs = () => { const getVal = (id) => (document.getElementById(id)?.value || "").trim(); - const enabled = document.getElementById("whyChooseUsEnabled")?.checked !== false; + const enabled = document.getElementById("whyChooseUsEnabled")?.checked === true; // Collect items const items = [];