const mongoose = require("mongoose"); const { Schema } = mongoose; // Reusable small schemas const LinkSchema = new Schema( { label: { type: String, default: "" }, href: { type: String, default: "" }, }, { _id: false }, ); const FloatingContactBrandSchema = new Schema( { imageSrc: { type: String, default: "" }, imageAlt: { type: String, default: "", maxlength: 60 }, }, { _id: false }, ); const FloatingContactTriggerSchema = new Schema( { imageSrc: { type: String, default: "" }, icon: { type: String, default: "fa-comments" }, }, { _id: false }, ); const FloatingContactActionSchema = new Schema( { id: { type: String, default: "" }, platform: { type: String, default: "" }, enabled: { type: Boolean, default: true }, label: { type: String, default: "", maxlength: 48 }, subtitle: { type: String, default: "", maxlength: 48 }, href: { type: String, default: "" }, iconImage: { type: String, default: "" }, iconType: { type: String, default: "iconClass" }, iconClass: { type: String, default: "" }, iconText: { type: String, default: "", maxlength: 12 }, order: { type: Number, default: 0 }, }, { _id: false }, ); const FloatingContactSchema = new Schema( { enabled: { type: Boolean, default: true }, position: { type: String, default: "bottom-right" }, panelTitle: { type: String, default: "", maxlength: 72 }, brand: { type: FloatingContactBrandSchema, default: () => ({}) }, trigger: { type: FloatingContactTriggerSchema, default: () => ({}) }, actions: { type: [FloatingContactActionSchema], default: [] }, }, { _id: false }, ); // Hero slide (for multiple hero items in slider) const HeroSlideSchema = new Schema( { title: { type: String, default: "" }, subtitle: { type: String, default: "" }, description: { type: String, default: "" }, primaryButton: { type: LinkSchema, default: () => ({}) }, secondaryButton: { type: LinkSchema, default: () => ({}) }, heroImage: { type: String, default: "" }, videoUrl: { type: String, default: "" }, }, { _id: false }, ); const HeroSchema = new Schema( { // Background for whole hero section backgroundImage: { type: String, default: "" }, // Multiple slides slides: { type: [HeroSlideSchema], default: [] }, // Legacy single-slide fields (backward compatible) title: { type: String, default: "" }, subtitle: { type: String, default: "" }, description: { type: String, default: "" }, primaryButton: { type: LinkSchema, default: () => ({}) }, secondaryButton: { type: LinkSchema, default: () => ({}) }, heroImage: { type: String, default: "" }, videoUrl: { type: String, default: "" }, }, { _id: false }, ); const WhyChooseUsItemSchema = new Schema( { icon: { type: String, default: "" }, title: { type: String, default: "" }, description: { type: String, default: "" }, }, { _id: false }, ); const WhyChooseUsSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, description: { type: String, default: "" }, highlightWord: { type: String, default: "" }, mainImage: { type: String, default: "" }, secondaryImage: { type: String, default: "" }, items: { type: [WhyChooseUsItemSchema], default: [] }, features: { type: [String], default: [] }, ctaButton: { type: LinkSchema, default: () => ({}) }, }, { _id: false }, ); const VisaSolutionItemSchema = new Schema( { number: { type: String, default: "" }, title: { type: String, default: "" }, description: { type: String, default: "" }, link: { type: String, default: "" }, }, { _id: false }, ); const VisaSolutionsSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, items: { type: [VisaSolutionItemSchema], default: [] }, }, { _id: false }, ); const VisaCountrySchema = new Schema( { name: { type: String, default: "" }, code: { type: String, default: "" }, flag: { type: String, default: "" }, link: { type: String, default: "" }, visaTypes: { type: [String], default: [] }, }, { _id: false }, ); const VisaCountriesSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, description: { type: String, default: "" }, countries: { type: [VisaCountrySchema], default: [] }, ctaButton: { type: LinkSchema, default: () => ({}) }, }, { _id: false }, ); const TestimonialSchema = new Schema( { name: { type: String, default: "" }, role: { type: String, default: "" }, country: { type: String, default: "" }, rating: { type: Number, default: 5 }, comment: { type: String, default: "" }, avatar: { type: String, default: "" }, }, { _id: false }, ); const TestimonialsSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, videoUrl: { type: String, default: "" }, videoThumbnail: { type: String, default: "" }, items: { type: [TestimonialSchema], default: [] }, }, { _id: false }, ); const VideoGallerySchema = new Schema( { heading: { type: String, default: "" }, videoUrl: { type: String, default: "" }, thumbnail: { type: String, default: "" }, }, { _id: false }, ); const FaqItemSchema = new Schema( { question: { type: String, default: "" }, answer: { type: String, default: "" }, }, { _id: false }, ); const FaqSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, description: { type: String, default: "" }, ctaButton: { type: LinkSchema, default: () => ({}) }, items: { type: [FaqItemSchema], default: [] }, }, { _id: false }, ); const AchievementItemSchema = new Schema( { value: { type: String, default: "" }, suffix: { type: String, default: "" }, label: { type: String, default: "" }, description: { type: String, default: "" }, }, { _id: false }, ); const AchievementsSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, items: { type: [AchievementItemSchema], default: [] }, }, { _id: false }, ); const VisaConsultancyItemSchema = new Schema( { name: { type: String, default: "" }, icon: { type: String, default: "" }, year: { type: String, default: "" }, }, { _id: false }, ); const VisaConsultancySchema = new Schema( { items: { type: [VisaConsultancyItemSchema], default: [] }, }, { _id: false }, ); const BrandItemSchema = new Schema( { logo: { type: String, default: "" }, }, { _id: false }, ); const BrandsSchema = new Schema( { items: { type: [BrandItemSchema], default: [] }, }, { _id: false }, ); const PartnersSchema = new Schema( { visaConsultancy: { type: VisaConsultancySchema, default: () => ({}) }, brands: { type: BrandsSchema, default: () => ({}) }, }, { _id: false }, ); const BlogPreviewItemSchema = new Schema( { title: { type: String, default: "" }, excerpt: { type: String, default: "" }, category: { type: String, default: "" }, date: { type: String, default: "" }, // keep as string for easy JSON compatibility (e.g. "2025-08-20") author: { name: { type: String, default: "" }, avatar: { type: String, default: "" }, }, comments: { type: Number, default: 0 }, link: { type: String, default: "" }, thumbnail: { type: String, default: "" }, }, { _id: false }, ); const BlogPreviewSchema = new Schema( { heading: { type: String, default: "" }, subheading: { type: String, default: "" }, ctaButton: { type: LinkSchema, default: () => ({}) }, items: { type: [BlogPreviewItemSchema], default: [] }, selectedBlogIds: [{ type: Schema.Types.ObjectId, ref: 'Blog' }], }, { _id: false }, ); /** * Home page content model * * NOTE: * - This schema is based on `hailearning.edu.vn/app/home.json`. * - `strict: false` keeps backward compatibility with any existing CMS-only sections * (e.g. about/missionVision/programs/newsletter/latestPosts...) that the admin UI might still send. */ const HomeSchema = new Schema( { hero: { type: HeroSchema, default: () => ({}) }, whyChooseUs: { type: WhyChooseUsSchema, default: () => ({}) }, visaSolutions: { type: VisaSolutionsSchema, default: () => ({}) }, visaCountries: { type: VisaCountriesSchema, default: () => ({}) }, testimonials: { type: TestimonialsSchema, default: () => ({}) }, videoGallery: { type: VideoGallerySchema, default: () => ({}) }, faq: { type: FaqSchema, default: () => ({}) }, achievements: { type: AchievementsSchema, default: () => ({}) }, partners: { type: PartnersSchema, default: () => ({}) }, blogPreview: { type: BlogPreviewSchema, default: () => ({}) }, floatingContact: { type: FloatingContactSchema, default: () => ({}) }, }, { timestamps: true, strict: false, }, ); module.exports = mongoose.model("Home", HomeSchema);