342 lines
9.0 KiB
Dart
342 lines
9.0 KiB
Dart
/// Represents a single CMS section from the landing page.
|
|
class CmsSection {
|
|
final String id;
|
|
final String pageSlug;
|
|
final String sectionKey;
|
|
final Map<String, dynamic> content;
|
|
final bool isPublished;
|
|
|
|
const CmsSection({
|
|
required this.id,
|
|
required this.pageSlug,
|
|
required this.sectionKey,
|
|
required this.content,
|
|
this.isPublished = true,
|
|
});
|
|
|
|
factory CmsSection.fromJson(Map<String, dynamic> json) {
|
|
return CmsSection(
|
|
id: json['id'] as String,
|
|
pageSlug: json['pageSlug'] as String? ?? '',
|
|
sectionKey: json['sectionKey'] as String? ?? '',
|
|
content: json['content'] as Map<String, dynamic>? ?? {},
|
|
isPublished: json['isPublished'] as bool? ?? true,
|
|
);
|
|
}
|
|
}
|
|
|
|
// --- Top Professionals Section ---
|
|
|
|
class TopProfessionalsContent {
|
|
final String title;
|
|
final String ctaText;
|
|
final String ctaButtonText;
|
|
final List<ProfessionalItem> agents;
|
|
final List<ProfessionalItem> lenders;
|
|
|
|
const TopProfessionalsContent({
|
|
this.title = 'Meet top real estate professionals',
|
|
this.ctaText = 'Discover Top Real Estate Agents in Our Network',
|
|
this.ctaButtonText = 'See All Agents',
|
|
this.agents = const [],
|
|
this.lenders = const [],
|
|
});
|
|
|
|
factory TopProfessionalsContent.fromJson(Map<String, dynamic> json) {
|
|
return TopProfessionalsContent(
|
|
title: json['title'] as String? ?? 'Meet top real estate professionals',
|
|
ctaText: json['ctaText'] as String? ??
|
|
'Discover Top Real Estate Agents in Our Network',
|
|
ctaButtonText: json['ctaButtonText'] as String? ?? 'See All Agents',
|
|
agents: (json['agents'] as List<dynamic>?)
|
|
?.map((e) =>
|
|
ProfessionalItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
lenders: (json['lenders'] as List<dynamic>?)
|
|
?.map((e) =>
|
|
ProfessionalItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
);
|
|
}
|
|
}
|
|
|
|
class ProfessionalItem {
|
|
final String? id;
|
|
final String name;
|
|
final String subtitle;
|
|
final String location;
|
|
final String experience;
|
|
final List<String> expertise;
|
|
final String imageUrl;
|
|
final double rating;
|
|
|
|
const ProfessionalItem({
|
|
this.id,
|
|
required this.name,
|
|
this.subtitle = '',
|
|
this.location = '',
|
|
this.experience = '',
|
|
this.expertise = const [],
|
|
this.imageUrl = '',
|
|
this.rating = 5.0,
|
|
});
|
|
|
|
factory ProfessionalItem.fromJson(Map<String, dynamic> json) {
|
|
return ProfessionalItem(
|
|
id: json['id'] as String?,
|
|
name: json['name'] as String? ?? '',
|
|
subtitle: json['subtitle'] as String? ?? '',
|
|
location: json['location'] as String? ?? '',
|
|
experience: json['experience'] as String? ?? '',
|
|
expertise: (json['expertise'] as List<dynamic>?)
|
|
?.map((e) => e.toString())
|
|
.toList() ??
|
|
[],
|
|
imageUrl: json['imageUrl'] as String? ?? '',
|
|
rating: (json['rating'] as num?)?.toDouble() ??
|
|
(json['averageRating'] as num?)?.toDouble() ??
|
|
5.0,
|
|
);
|
|
}
|
|
}
|
|
|
|
// --- Hero Section ---
|
|
|
|
class HeroContent {
|
|
final String headline;
|
|
final String description;
|
|
final String ctaButtonText;
|
|
final String helperText;
|
|
|
|
const HeroContent({
|
|
this.headline = '',
|
|
this.description = '',
|
|
this.ctaButtonText = '',
|
|
this.helperText = '',
|
|
});
|
|
|
|
factory HeroContent.fromJson(Map<String, dynamic> json) {
|
|
return HeroContent(
|
|
headline: json['headline'] as String? ?? '',
|
|
description: json['description'] as String? ?? '',
|
|
ctaButtonText: json['ctaButtonText'] as String? ?? '',
|
|
helperText: json['helperText'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
// --- Features Section ---
|
|
|
|
class FeaturedAgentItem {
|
|
final String? id;
|
|
final String name;
|
|
final String role;
|
|
final String rating;
|
|
final String location;
|
|
final String experience;
|
|
final String imageUrl;
|
|
|
|
const FeaturedAgentItem({
|
|
this.id,
|
|
this.name = '',
|
|
this.role = '',
|
|
this.rating = '',
|
|
this.location = '',
|
|
this.experience = '',
|
|
this.imageUrl = '',
|
|
});
|
|
|
|
factory FeaturedAgentItem.fromJson(Map<String, dynamic> json) {
|
|
return FeaturedAgentItem(
|
|
id: json['id'] as String?,
|
|
name: json['name'] as String? ?? '',
|
|
role: json['role'] as String? ?? '',
|
|
rating: json['rating'] as String? ?? '',
|
|
location: json['location'] as String? ?? '',
|
|
experience: json['experience'] as String? ?? '',
|
|
imageUrl: json['imageUrl'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
class FeaturesContent {
|
|
final String title;
|
|
final String subtitle;
|
|
final List<FeatureItem> features;
|
|
final List<FeaturedAgentItem> featuredAgents;
|
|
|
|
const FeaturesContent({
|
|
this.title = '',
|
|
this.subtitle = '',
|
|
this.features = const [],
|
|
this.featuredAgents = const [],
|
|
});
|
|
|
|
factory FeaturesContent.fromJson(Map<String, dynamic> json) {
|
|
return FeaturesContent(
|
|
title: json['title'] as String? ?? '',
|
|
subtitle: json['subtitle'] as String? ?? '',
|
|
features: (json['features'] as List<dynamic>?)
|
|
?.map(
|
|
(e) => FeatureItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
featuredAgents: (json['featuredAgents'] as List<dynamic>?)
|
|
?.map(
|
|
(e) => FeaturedAgentItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
);
|
|
}
|
|
}
|
|
|
|
class FeatureItem {
|
|
final String iconPath;
|
|
final String title;
|
|
final String description;
|
|
|
|
const FeatureItem({
|
|
this.iconPath = '',
|
|
this.title = '',
|
|
this.description = '',
|
|
});
|
|
|
|
factory FeatureItem.fromJson(Map<String, dynamic> json) {
|
|
return FeatureItem(
|
|
iconPath: json['iconPath'] as String? ?? '',
|
|
title: json['title'] as String? ?? '',
|
|
description: json['description'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
// --- Testimonials Section ---
|
|
|
|
class TestimonialsContent {
|
|
final String title;
|
|
final String subtitle;
|
|
final String ratingInfo;
|
|
final List<StatItem> stats;
|
|
final List<TestimonialItem> testimonials;
|
|
|
|
const TestimonialsContent({
|
|
this.title = '',
|
|
this.subtitle = '',
|
|
this.ratingInfo = '',
|
|
this.stats = const [],
|
|
this.testimonials = const [],
|
|
});
|
|
|
|
factory TestimonialsContent.fromJson(Map<String, dynamic> json) {
|
|
return TestimonialsContent(
|
|
title: json['title'] as String? ?? '',
|
|
subtitle: json['subtitle'] as String? ?? '',
|
|
ratingInfo: json['ratingInfo'] as String? ?? '',
|
|
stats: (json['stats'] as List<dynamic>?)
|
|
?.map((e) => StatItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
testimonials: (json['testimonials'] as List<dynamic>?)
|
|
?.map((e) =>
|
|
TestimonialItem.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
);
|
|
}
|
|
}
|
|
|
|
class StatItem {
|
|
final String iconPath;
|
|
final String boldText;
|
|
final String normalText;
|
|
|
|
const StatItem({
|
|
this.iconPath = '',
|
|
this.boldText = '',
|
|
this.normalText = '',
|
|
});
|
|
|
|
factory StatItem.fromJson(Map<String, dynamic> json) {
|
|
return StatItem(
|
|
iconPath: json['iconPath'] as String? ?? '',
|
|
boldText: json['boldText'] as String? ?? '',
|
|
normalText: json['normalText'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
class TestimonialItem {
|
|
final int rating;
|
|
final String title;
|
|
final String content;
|
|
final String author;
|
|
final String role;
|
|
|
|
const TestimonialItem({
|
|
this.rating = 5,
|
|
this.title = '',
|
|
this.content = '',
|
|
this.author = '',
|
|
this.role = '',
|
|
});
|
|
|
|
factory TestimonialItem.fromJson(Map<String, dynamic> json) {
|
|
return TestimonialItem(
|
|
rating: json['rating'] as int? ?? 5,
|
|
title: json['title'] as String? ?? '',
|
|
content: json['content'] as String? ?? '',
|
|
author: json['author'] as String? ?? '',
|
|
role: json['role'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Parsed landing page content from all CMS sections.
|
|
class LandingPageContent {
|
|
final HeroContent? hero;
|
|
final FeaturesContent? features;
|
|
final TopProfessionalsContent? topProfessionals;
|
|
final TestimonialsContent? testimonials;
|
|
|
|
const LandingPageContent({
|
|
this.hero,
|
|
this.features,
|
|
this.topProfessionals,
|
|
this.testimonials,
|
|
});
|
|
|
|
factory LandingPageContent.fromSections(List<CmsSection> sections) {
|
|
HeroContent? hero;
|
|
FeaturesContent? features;
|
|
TopProfessionalsContent? topProfessionals;
|
|
TestimonialsContent? testimonials;
|
|
|
|
for (final section in sections) {
|
|
switch (section.sectionKey) {
|
|
case 'hero':
|
|
hero = HeroContent.fromJson(section.content);
|
|
break;
|
|
case 'features':
|
|
features = FeaturesContent.fromJson(section.content);
|
|
break;
|
|
case 'topProfessionals':
|
|
topProfessionals =
|
|
TopProfessionalsContent.fromJson(section.content);
|
|
break;
|
|
case 'testimonials':
|
|
testimonials = TestimonialsContent.fromJson(section.content);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return LandingPageContent(
|
|
hero: hero,
|
|
features: features,
|
|
topProfessionals: topProfessionals,
|
|
testimonials: testimonials,
|
|
);
|
|
}
|
|
}
|