forked from UKSOURCE/cms.hailearning.edu.vn
308 lines
8.3 KiB
JavaScript
308 lines
8.3 KiB
JavaScript
const mongoose = require("mongoose");
|
|
|
|
const { Schema } = mongoose;
|
|
|
|
// Reusable small schemas
|
|
const LinkSchema = new Schema(
|
|
{
|
|
label: { type: String, default: "" },
|
|
href: { type: String, 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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
// 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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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(
|
|
{
|
|
// Toggle visibility on frontend
|
|
enabled: { type: Boolean, default: true },
|
|
|
|
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: () => ({}) },
|
|
},
|
|
{
|
|
timestamps: true,
|
|
strict: false,
|
|
},
|
|
);
|
|
|
|
module.exports = mongoose.model("Home", HomeSchema);
|
|
|