Files
mobile-app/lib/features/home/presentation/widgets/testimonials_section.dart

211 lines
7.2 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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 testimonials — matches web's hardcoded defaultTestimonials fallback.
const _defaultTestimonials = [
TestimonialItem(
rating: 5,
title: 'I have been working with Lorem ..',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
),
TestimonialItem(
rating: 5,
title: 'I have been working with Lorem ..',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
),
TestimonialItem(
rating: 5,
title: 'I have been working with Lorem ..',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
),
];
/// Default section content — matches web's hardcoded defaultContent fallback.
const _defaultContent = TestimonialsContent(
title: "Our Clients' Trust Is Our Foundation",
subtitle:
'We help buyers, sellers, and investors close successful real estate deals with confidence in every transaction.',
ratingInfo:
'Clients rate our real estate services 4.9 out of 5 on average, based on recent client reviews.',
stats: [
StatItem(
iconPath: 'cities',
boldText: '25+ Cities &',
normalText: 'neighborhoods served',
),
StatItem(
iconPath: 'properties',
boldText: '1,000+ Properties',
normalText: 'bought and sold for our clients.',
),
],
testimonials: _defaultTestimonials,
);
class TestimonialsSection extends ConsumerWidget {
const TestimonialsSection({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final homeState = ref.watch(homeProvider);
final cmsTestimonials = homeState.content?.testimonials;
// Use CMS data if available with non-empty testimonials, otherwise fallback
final data =
(cmsTestimonials != null && cmsTestimonials.testimonials.isNotEmpty)
? cmsTestimonials
: _defaultContent;
final title = data.title.isNotEmpty ? data.title : _defaultContent.title;
final subtitle =
data.subtitle.isNotEmpty ? data.subtitle : _defaultContent.subtitle;
final testimonials =
data.testimonials.isNotEmpty ? data.testimonials : _defaultTestimonials;
return Column(
children: [
// Section header
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: 8),
Text(
subtitle,
textAlign: TextAlign.center,
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontWeight: FontWeight.w400,
color: AppColors.primaryDark,
),
),
],
),
),
const SizedBox(height: 24),
// Testimonial cards carousel
SizedBox(
height: 380,
child: ListView.builder(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 24),
itemCount: testimonials.length,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.only(right: 16),
child: _buildTestimonialCard(testimonials[index]),
),
),
),
],
);
}
Widget _buildTestimonialCard(TestimonialItem testimonial) {
return Container(
width: 315,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: AppColors.primaryDark,
borderRadius: BorderRadius.circular(15),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Quote icon
const Text(
'\u201C',
style: TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 48,
fontWeight: FontWeight.w700,
color: AppColors.accentOrange,
height: 0.8,
),
),
const SizedBox(height: 8),
Text(
testimonial.title,
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 14,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
const SizedBox(height: 12),
Expanded(
child: Text(
testimonial.content,
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontWeight: FontWeight.w400,
color: Colors.white,
),
),
),
const SizedBox(height: 16),
// Stars
Row(
children: List.generate(
testimonial.rating,
(index) => const Padding(
padding: EdgeInsets.only(right: 4),
child: Icon(
Icons.star,
color: AppColors.accentOrange,
size: 18,
),
),
),
),
const SizedBox(height: 12),
// Author info
Text(
testimonial.author,
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
Text(
testimonial.role,
style: const TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
],
),
);
}
}