176 lines
5.8 KiB
Dart
176 lines
5.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:real_estate_mobile/core/constants/app_colors.dart';
|
|
import 'package:real_estate_mobile/features/home/data/models/landing_page_content.dart';
|
|
import 'package:real_estate_mobile/features/home/presentation/providers/home_provider.dart';
|
|
|
|
/// Default content — matches web's hardcoded defaultContent fallback.
|
|
const _defaultContent = TestimonialsContent(
|
|
title: 'Consumer Protection is Our Foundation',
|
|
subtitle:
|
|
"Buying or selling your home is one of the largest decisions you will make in your life. Don't let yourself be chased by salesmen. Find the service provider that matches your unique needs.",
|
|
ratingInfo:
|
|
'Clients rate our real estate services 4.9 out of 5 on average, based on recent client reviews.',
|
|
stats: [
|
|
StatItem(
|
|
iconPath: 'cities',
|
|
boldText: '3 states',
|
|
normalText: 'and counting',
|
|
),
|
|
StatItem(
|
|
iconPath: 'properties',
|
|
boldText: 'Hundreds of',
|
|
normalText: 'Professionals',
|
|
),
|
|
],
|
|
testimonials: [],
|
|
);
|
|
|
|
/// Map of stat icon keys to local SVG asset paths and Material fallback icons.
|
|
const _statIconMap = {
|
|
'cities': ('assets/icons/cities_icon.svg', Icons.location_city),
|
|
'properties': ('assets/icons/properties_icon.svg', Icons.home_work),
|
|
// CMS web-path keys
|
|
'/assets/icons/cities-icon.svg': ('assets/icons/cities_icon.svg', Icons.location_city),
|
|
'/assets/icons/properties-icon.svg': ('assets/icons/properties_icon.svg', Icons.home_work),
|
|
};
|
|
|
|
class TrustStatsSection extends ConsumerWidget {
|
|
const TrustStatsSection({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final homeState = ref.watch(homeProvider);
|
|
final cmsTestimonials = homeState.content?.testimonials;
|
|
|
|
// Use CMS data if available, otherwise fallback (same pattern as web)
|
|
final data = cmsTestimonials ?? _defaultContent;
|
|
|
|
final title = data.title.isNotEmpty ? data.title : _defaultContent.title;
|
|
final subtitle =
|
|
data.subtitle.isNotEmpty ? data.subtitle : _defaultContent.subtitle;
|
|
final stats =
|
|
data.stats.isNotEmpty ? data.stats : _defaultContent.stats;
|
|
final ratingInfo = data.ratingInfo.isNotEmpty
|
|
? data.ratingInfo
|
|
: _defaultContent.ratingInfo;
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
title,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
fontFamily: 'Fractul',
|
|
fontSize: 25,
|
|
fontWeight: FontWeight.w700,
|
|
color: AppColors.primaryDark,
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
subtitle,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
fontFamily: 'Fractul',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: AppColors.primaryDark,
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
ratingInfo,
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
fontFamily: 'SourceSerif4',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: AppColors.primaryDark,
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
const Divider(color: AppColors.divider),
|
|
const SizedBox(height: 16),
|
|
// Stats (group centered, content left-aligned)
|
|
Align(
|
|
alignment: Alignment.center,
|
|
child: IntrinsicWidth(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: stats
|
|
.map((stat) => Padding(
|
|
padding: const EdgeInsets.only(bottom: 12),
|
|
child: _buildStatItem(stat),
|
|
))
|
|
.toList(),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildStatItem(StatItem stat) {
|
|
final iconEntry = _statIconMap[stat.iconPath];
|
|
final svgPath = iconEntry?.$1;
|
|
final fallbackIcon = iconEntry?.$2 ?? Icons.info_outline;
|
|
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(right: 10, top: 2),
|
|
child: svgPath != null
|
|
? SvgPicture.asset(
|
|
svgPath,
|
|
width: 27,
|
|
height: 27,
|
|
colorFilter: const ColorFilter.mode(
|
|
AppColors.accentOrange,
|
|
BlendMode.srcIn,
|
|
),
|
|
)
|
|
: Icon(
|
|
fallbackIcon,
|
|
size: 27,
|
|
color: AppColors.accentOrange,
|
|
),
|
|
),
|
|
Flexible(
|
|
child: RichText(
|
|
text: TextSpan(
|
|
children: [
|
|
TextSpan(
|
|
text: '${stat.boldText}\n',
|
|
style: const TextStyle(
|
|
fontFamily: 'SourceSerif4',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w700,
|
|
color: AppColors.primaryDark,
|
|
),
|
|
),
|
|
TextSpan(
|
|
text: stat.normalText,
|
|
style: const TextStyle(
|
|
fontFamily: 'SourceSerif4',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: AppColors.primaryDark,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
}
|