2026-03-08 12:15:15 +05:30
import ' package:flutter/material.dart ' ;
import ' package:flutter_riverpod/flutter_riverpod.dart ' ;
import ' package:go_router/go_router.dart ' ;
import ' package:real_estate_mobile/core/constants/app_colors.dart ' ;
import ' package:real_estate_mobile/core/network/api_client.dart ' ;
import ' package:real_estate_mobile/core/widgets/s3_image.dart ' ;
// ── Data models (matching web CMS types) ──
class _AboutHero {
final String badge ;
final String headline ;
final String description ;
final String ctaButtonText ;
final String bannerImageUrl ;
final String bannerOverlayText ;
const _AboutHero ( {
this . badge = ' Our Mission ' ,
this . headline = ' Connecting You with Trusted Agents. ' ,
this . description =
' We believe finding the right home shouldn \u2019 t be complicated. Our platform bridges the gap between buyers, sellers, and verified real estate agents for a smooth and transparent experience. ' ,
this . ctaButtonText = ' Find Your Agent ' ,
this . bannerImageUrl = ' ' ,
this . bannerOverlayText = ' Building the future of property. ' ,
} ) ;
factory _AboutHero . fromJson ( Map < String , dynamic > json ) {
return _AboutHero (
badge: json [ ' badge ' ] as String ? ? ? ' Our Mission ' ,
headline: json [ ' headline ' ] as String ? ? ? ' Connecting You with Trusted Agents. ' ,
description: json [ ' description ' ] as String ? ? ?
' We believe finding the right home shouldn \u2019 t be complicated. Our platform bridges the gap between buyers, sellers, and verified real estate agents for a smooth and transparent experience. ' ,
ctaButtonText: json [ ' ctaButtonText ' ] as String ? ? ? ' Find Your Agent ' ,
bannerImageUrl: json [ ' bannerImageUrl ' ] as String ? ? ? ' ' ,
bannerOverlayText: json [ ' bannerOverlayText ' ] as String ? ? ? ' Building the future of property. ' ,
) ;
}
}
class _AboutStatItem {
final String value ;
final String label ;
const _AboutStatItem ( { required this . value , required this . label } ) ;
factory _AboutStatItem . fromJson ( Map < String , dynamic > json ) {
return _AboutStatItem (
value: json [ ' value ' ] as String ? ? ? ' ' ,
label: json [ ' label ' ] as String ? ? ? ' ' ,
) ;
}
}
class _AboutFeatureItem {
final String iconPath ;
final String title ;
final String description ;
const _AboutFeatureItem ( {
required this . iconPath ,
required this . title ,
required this . description ,
} ) ;
factory _AboutFeatureItem . fromJson ( Map < String , dynamic > json ) {
return _AboutFeatureItem (
iconPath: json [ ' iconPath ' ] as String ? ? ? ' ' ,
title: json [ ' title ' ] as String ? ? ? ' ' ,
description: json [ ' description ' ] as String ? ? ? ' ' ,
) ;
}
}
class _AboutTeamMember {
final String name ;
final String role ;
final String imageUrl ;
const _AboutTeamMember ( {
required this . name ,
required this . role ,
required this . imageUrl ,
} ) ;
factory _AboutTeamMember . fromJson ( Map < String , dynamic > json ) {
return _AboutTeamMember (
name: json [ ' name ' ] as String ? ? ? ' ' ,
role: json [ ' role ' ] as String ? ? ? ' ' ,
imageUrl: json [ ' imageUrl ' ] as String ? ? ? ' ' ,
) ;
}
}
class _AboutCta {
final String title ;
final String description ;
final String buttonText ;
const _AboutCta ( {
this . title = ' Ready to find a agent ' ,
this . description =
' Search and connect with verified real estate agents who match your needs, location, and goals. ' ,
this . buttonText = ' Find Agents Now ' ,
} ) ;
factory _AboutCta . fromJson ( Map < String , dynamic > json ) {
return _AboutCta (
title: json [ ' title ' ] as String ? ? ? ' Ready to find a agent ' ,
description: json [ ' description ' ] as String ? ? ?
' Search and connect with verified real estate agents who match your needs, location, and goals. ' ,
buttonText: json [ ' buttonText ' ] as String ? ? ? ' Find Agents Now ' ,
) ;
}
}
// ── Defaults ──
const _defaultStats = [
_AboutStatItem ( value: ' 15k+ ' , label: ' Verified Agents ' ) ,
_AboutStatItem ( value: ' 98% ' , label: ' Customer Satisfaction ' ) ,
] ;
const _defaultFeatures = [
_AboutFeatureItem (
iconPath: ' ' ,
title: ' Verified Agents ' ,
description:
' All agents on our platform are carefully verified to ensure trust, proven expertise, and consistent service, helping users connect with reliable professionals and enjoy a smooth, confident, and transparent property journey ' ,
) ,
_AboutFeatureItem (
iconPath: ' ' ,
title: ' Total Transparency ' ,
description:
' We maintain complete transparency by clearly displaying agent details, reviews, and activity, allowing users to make informed decisions with confidence, clarity, and trust throughout their entire property journey. ' ,
) ,
_AboutFeatureItem (
iconPath: ' ' ,
title: ' Simple Journey ' ,
description:
' Our platform simplifies every step of the property process, from discovering the right agent to closing with confidence, making the experience smooth, fast, and stress-free for users at every stage. ' ,
) ,
] ;
const _defaultTeamMembers = [
_AboutTeamMember ( name: ' Andrew ' , role: ' Founder & CEO ' , imageUrl: ' asset://professional-1 ' ) ,
_AboutTeamMember ( name: ' Thomas ' , role: ' Co-Founder ' , imageUrl: ' asset://professional-2 ' ) ,
_AboutTeamMember ( name: ' Darren ' , role: ' Advisor ' , imageUrl: ' asset://professional-3 ' ) ,
] ;
// ── State ──
class _AboutState {
final bool isLoading ;
final _AboutHero hero ;
final List < _AboutStatItem > stats ;
final String featuresBadge ;
final List < _AboutFeatureItem > features ;
final String teamTitle ;
final String teamSubtitle ;
final List < _AboutTeamMember > teamMembers ;
final _AboutCta cta ;
final int activeTeamIndex ;
const _AboutState ( {
this . isLoading = true ,
this . hero = const _AboutHero ( ) ,
this . stats = _defaultStats ,
this . featuresBadge = ' Why Choose Us ' ,
this . features = _defaultFeatures ,
this . teamTitle = ' Meet the minds behind the platform ' ,
this . teamSubtitle =
' We are a team of passionate innovators, real estate experts, and designers working together to redefine how people connect with trusted agents. ' ,
this . teamMembers = _defaultTeamMembers ,
this . cta = const _AboutCta ( ) ,
this . activeTeamIndex = 0 ,
} ) ;
_AboutState copyWith ( {
bool ? isLoading ,
_AboutHero ? hero ,
List < _AboutStatItem > ? stats ,
String ? featuresBadge ,
List < _AboutFeatureItem > ? features ,
String ? teamTitle ,
String ? teamSubtitle ,
List < _AboutTeamMember > ? teamMembers ,
_AboutCta ? cta ,
int ? activeTeamIndex ,
} ) {
return _AboutState (
isLoading: isLoading ? ? this . isLoading ,
hero: hero ? ? this . hero ,
stats: stats ? ? this . stats ,
featuresBadge: featuresBadge ? ? this . featuresBadge ,
features: features ? ? this . features ,
teamTitle: teamTitle ? ? this . teamTitle ,
teamSubtitle: teamSubtitle ? ? this . teamSubtitle ,
teamMembers: teamMembers ? ? this . teamMembers ,
cta: cta ? ? this . cta ,
activeTeamIndex: activeTeamIndex ? ? this . activeTeamIndex ,
) ;
}
}
// ── Provider ──
class _AboutNotifier extends StateNotifier < _AboutState > {
_AboutNotifier ( ) : super ( const _AboutState ( ) ) {
_load ( ) ;
}
Future < void > _load ( ) async {
try {
final response = await ApiClient . instance . dio . get ( ' /cms/page/about ' ) ;
final data = response . data [ ' data ' ] as List < dynamic > ? ;
if ( data ! = null ) {
for ( final record in data ) {
final map = record as Map < String , dynamic > ;
final sectionKey = map [ ' sectionKey ' ] as String ? ;
final content = map [ ' content ' ] as Map < String , dynamic > ? ;
if ( content = = null ) continue ;
switch ( sectionKey ) {
case ' hero ' :
if ( content [ ' headline ' ] ! = null | | content [ ' description ' ] ! = null ) {
state = state . copyWith ( hero: _AboutHero . fromJson ( content ) ) ;
}
case ' stats ' :
final statsList = content [ ' stats ' ] as List < dynamic > ? ;
if ( statsList ! = null & & statsList . isNotEmpty ) {
state = state . copyWith (
stats: statsList
. map ( ( e ) = > _AboutStatItem . fromJson ( e as Map < String , dynamic > ) )
. toList ( ) ,
) ;
}
case ' features ' :
final badge = content [ ' badge ' ] as String ? ;
final featuresList = content [ ' features ' ] as List < dynamic > ? ;
if ( badge ! = null ) {
state = state . copyWith ( featuresBadge: badge ) ;
}
if ( featuresList ! = null & & featuresList . isNotEmpty ) {
state = state . copyWith (
features: featuresList
. map ( ( e ) = > _AboutFeatureItem . fromJson ( e as Map < String , dynamic > ) )
. toList ( ) ,
) ;
}
case ' team ' :
final title = content [ ' title ' ] as String ? ;
final subtitle = content [ ' subtitle ' ] as String ? ;
final membersList = content [ ' members ' ] as List < dynamic > ? ;
if ( title ! = null ) state = state . copyWith ( teamTitle: title ) ;
if ( subtitle ! = null ) state = state . copyWith ( teamSubtitle: subtitle ) ;
if ( membersList ! = null & & membersList . isNotEmpty ) {
state = state . copyWith (
teamMembers: membersList
. map ( ( e ) = > _AboutTeamMember . fromJson ( e as Map < String , dynamic > ) )
. toList ( ) ,
) ;
}
case ' cta ' :
if ( content [ ' title ' ] ! = null | | content [ ' description ' ] ! = null ) {
state = state . copyWith ( cta: _AboutCta . fromJson ( content ) ) ;
}
}
}
}
} catch ( _ ) {
// Fall through to defaults
}
state = state . copyWith ( isLoading: false ) ;
}
void setActiveTeamIndex ( int index ) {
state = state . copyWith ( activeTeamIndex: index ) ;
}
}
final _aboutProvider =
StateNotifierProvider . autoDispose < _AboutNotifier , _AboutState > ( ( ref ) {
return _AboutNotifier ( ) ;
} ) ;
// ── Feature icon mapping (fallback when CMS has no iconPath) ──
const _featureIconFallback = < String , IconData > {
' Verified Agents ' : Icons . verified ,
' Total Transparency ' : Icons . lock_outline ,
' Simple Journey ' : Icons . check_circle_outline ,
} ;
// ── Screen ──
class AboutScreen extends ConsumerWidget {
const AboutScreen ( { super . key } ) ;
@ override
Widget build ( BuildContext context , WidgetRef ref ) {
final state = ref . watch ( _aboutProvider ) ;
2026-03-08 16:05:08 +05:30
if ( state . isLoading ) {
return const Center (
child: CircularProgressIndicator (
color: AppColors . accentOrange ,
2026-03-08 12:15:15 +05:30
) ,
2026-03-08 16:05:08 +05:30
) ;
}
return SingleChildScrollView (
physics: const AlwaysScrollableScrollPhysics ( ) ,
child: Column (
children: [
const SizedBox ( height: 18 ) ,
_buildHeroTitle ( state . hero . headline ) ,
const SizedBox ( height: 16 ) ,
_buildHeroSubtitle ( state . hero . description ) ,
const SizedBox ( height: 24 ) ,
_buildBannerImage ( state . hero . bannerImageUrl ) ,
const SizedBox ( height: 10 ) ,
_buildBannerCaption ( state . hero . bannerOverlayText ) ,
const SizedBox ( height: 16 ) ,
_buildStatsRow ( state . stats ) ,
const SizedBox ( height: 32 ) ,
_buildSectionTitle ( state . featuresBadge ) ,
const SizedBox ( height: 12 ) ,
_buildWhyChooseUsSubtitle ( ) ,
const SizedBox ( height: 24 ) ,
. . . state . features . map ( ( f ) = > Padding (
padding: const EdgeInsets . only ( bottom: 15 ) ,
child: _buildFeatureCard ( f ) ,
) ) ,
const SizedBox ( height: 25 ) ,
_buildTeamSection ( context , ref , state ) ,
const SizedBox ( height: 40 ) ,
_buildCtaSection ( context , state . cta ) ,
const SizedBox ( height: 30 ) ,
] ,
2026-03-08 12:15:15 +05:30
) ,
) ;
}
// -- Hero Title --
Widget _buildHeroTitle ( String text ) {
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 40 ) ,
child: Text (
text ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 25 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ;
}
// -- Hero Subtitle --
Widget _buildHeroSubtitle ( String text ) {
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 40 ) ,
child: Text (
text ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w500 ,
color: AppColors . primaryDark ,
) ,
) ,
) ;
}
// -- Banner Image (from CMS or fallback to local asset) --
Widget _buildBannerImage ( String imageUrl ) {
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 57 ) ,
child: ClipRRect (
borderRadius: BorderRadius . circular ( 15 ) ,
child: SizedBox (
height: 295 ,
width: double . infinity ,
child: imageUrl . isNotEmpty
? S3Image (
imageUrl: imageUrl ,
height: 295 ,
fit: BoxFit . cover ,
errorWidget: ( context ) = > Image . asset (
' assets/images/about_cityscape.png ' ,
height: 295 ,
width: double . infinity ,
fit: BoxFit . cover ,
) ,
)
: Image . asset (
' assets/images/about_cityscape.png ' ,
height: 295 ,
width: double . infinity ,
fit: BoxFit . cover ,
) ,
) ,
) ,
) ;
}
// -- Banner Caption --
Widget _buildBannerCaption ( String text ) {
return Center (
child: Text (
text ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 14 ,
fontWeight: FontWeight . w500 ,
color: AppColors . primaryDark ,
) ,
) ,
) ;
}
// -- Stats Row (dynamic) --
Widget _buildStatsRow ( List < _AboutStatItem > stats ) {
if ( stats . isEmpty ) return const SizedBox . shrink ( ) ;
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 40 ) ,
child: Row (
mainAxisAlignment: MainAxisAlignment . spaceAround ,
children: stats . map ( ( s ) = > _buildStatItem ( s . value , s . label ) ) . toList ( ) ,
) ,
) ;
}
Widget _buildStatItem ( String value , String label ) {
return Column (
children: [
Text (
value ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 14 ,
fontWeight: FontWeight . w500 ,
color: AppColors . accentOrange ,
) ,
) ,
const SizedBox ( height: 2 ) ,
Text (
label ,
style: const TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w400 ,
color: AppColors . primaryDark ,
) ,
) ,
] ,
) ;
}
// -- Section Title --
Widget _buildSectionTitle ( String text ) {
return Center (
child: Text (
text ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 25 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ;
}
// -- Why Choose Us Subtitle --
Widget _buildWhyChooseUsSubtitle ( ) {
return const Padding (
padding: EdgeInsets . symmetric ( horizontal: 65 ) ,
child: Text (
' Our core principles guide every interaction, ensuring you feel confident and supported at every step. ' ,
textAlign: TextAlign . center ,
style: TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w400 ,
color: AppColors . primaryDark ,
) ,
) ,
) ;
}
// -- Feature Card (dynamic with S3 icon support) --
Widget _buildFeatureCard ( _AboutFeatureItem feature ) {
final fallbackIcon = _featureIconFallback [ feature . title ] ? ? Icons . star_outline ;
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 57 ) ,
child: Container (
padding: const EdgeInsets . symmetric ( horizontal: 24 , vertical: 24 ) ,
decoration: BoxDecoration (
borderRadius: BorderRadius . circular ( 15 ) ,
border: Border . all (
color: AppColors . primaryDark . withValues ( alpha: 0.1 ) ,
width: 0.1 ,
) ,
) ,
child: Column (
children: [
if ( feature . iconPath . isNotEmpty )
SizedBox (
width: 36 ,
height: 36 ,
child: S3Image (
imageUrl: feature . iconPath ,
width: 36 ,
height: 36 ,
fit: BoxFit . contain ,
errorWidget: ( _ ) = > Icon (
fallbackIcon ,
size: 36 ,
color: AppColors . accentOrange ,
) ,
) ,
)
else
Icon (
fallbackIcon ,
size: 36 ,
color: AppColors . accentOrange ,
) ,
const SizedBox ( height: 10 ) ,
Text (
feature . title ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 14 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
const SizedBox ( height: 8 ) ,
Text (
feature . description ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w400 ,
color: AppColors . primaryDark ,
height: 1.5 ,
) ,
) ,
] ,
) ,
) ,
) ;
}
// -- Team Section (dynamic with carousel) --
Widget _buildTeamSection (
BuildContext context ,
WidgetRef ref ,
_AboutState state ,
) {
final members = state . teamMembers ;
if ( members . isEmpty ) return const SizedBox . shrink ( ) ;
final activeIndex = state . activeTeamIndex . clamp ( 0 , members . length - 1 ) ;
final screenWidth = MediaQuery . of ( context ) . size . width ;
final cardWidth = screenWidth - ( 69 * 2 ) ;
return Column (
children: [
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 57 ) ,
child: Text (
state . teamTitle ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 25 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ,
const SizedBox ( height: 16 ) ,
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 57 ) ,
child: Text (
state . teamSubtitle ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w400 ,
color: AppColors . primaryDark ,
) ,
) ,
) ,
const SizedBox ( height: 40 ) ,
// Team carousel
SizedBox (
height: 330 ,
child: PageView . builder (
itemCount: members . length ,
controller: PageController (
viewportFraction: cardWidth / screenWidth ,
) ,
onPageChanged: ( index ) {
ref . read ( _aboutProvider . notifier ) . setActiveTeamIndex ( index ) ;
} ,
itemBuilder: ( context , index ) {
final member = members [ index ] ;
return Padding (
padding: const EdgeInsets . symmetric ( horizontal: 4 ) ,
child: Container (
decoration: BoxDecoration (
borderRadius: BorderRadius . circular ( 15 ) ,
border: Border . all (
color: AppColors . primaryDark . withValues ( alpha: 0.1 ) ,
width: 0.1 ,
) ,
) ,
child: Column (
children: [
const SizedBox ( height: 19 ) ,
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 16 ) ,
child: ClipRRect (
borderRadius: BorderRadius . circular ( 15 ) ,
child: SizedBox (
height: 211 ,
width: double . infinity ,
child: _buildTeamMemberImage ( member . imageUrl ) ,
) ,
) ,
) ,
const SizedBox ( height: 16 ) ,
Text (
member . name ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 14 ,
fontWeight: FontWeight . w700 ,
color: Colors . black ,
) ,
) ,
const SizedBox ( height: 4 ) ,
Text (
member . role ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 14 ,
fontWeight: FontWeight . w300 ,
color: Colors . black ,
) ,
) ,
] ,
) ,
) ,
) ;
} ,
) ,
) ,
const SizedBox ( height: 16 ) ,
// Page indicator
if ( members . length > 1 )
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 58 ) ,
child: LayoutBuilder (
builder: ( context , constraints ) {
final totalWidth = constraints . maxWidth ;
final segmentWidth = totalWidth / members . length ;
return Stack (
children: [
Container (
height: 5 ,
decoration: BoxDecoration (
color: Colors . white ,
borderRadius: BorderRadius . circular ( 15 ) ,
border: Border . all (
color: AppColors . primaryDark . withValues ( alpha: 0.1 ) ,
width: 0.1 ,
) ,
) ,
) ,
AnimatedPositioned (
duration: const Duration ( milliseconds: 200 ) ,
left: segmentWidth * activeIndex ,
child: Container (
height: 5 ,
width: segmentWidth ,
decoration: BoxDecoration (
color: AppColors . primaryDark ,
borderRadius: BorderRadius . circular ( 15 ) ,
) ,
) ,
) ,
] ,
) ;
} ,
) ,
) ,
] ,
) ;
}
// -- Team member image (handles asset://, S3 keys, and URLs) --
Widget _buildTeamMemberImage ( String imageUrl ) {
const placeholder = _TeamMemberPlaceholder ( ) ;
if ( imageUrl . isEmpty ) return placeholder ;
// Local asset images (defaults)
if ( imageUrl . startsWith ( ' asset:// ' ) ) {
final name = imageUrl . replaceFirst ( ' asset:// ' , ' ' ) ;
return Image . asset (
' assets/images/ $ name .jpg ' ,
height: 211 ,
width: double . infinity ,
fit: BoxFit . cover ,
errorBuilder: ( context , error , stackTrace ) = > placeholder ,
) ;
}
// S3 key or URL from CMS
return S3Image (
imageUrl: imageUrl ,
height: 211 ,
fit: BoxFit . cover ,
placeholder: ( _ ) = > placeholder ,
errorWidget: ( _ ) = > placeholder ,
) ;
}
// -- CTA Section (dynamic) --
Widget _buildCtaSection ( BuildContext context , _AboutCta cta ) {
return Column (
children: [
Text (
cta . title ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 25 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
const SizedBox ( height: 16 ) ,
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 83 ) ,
child: Text (
cta . description ,
textAlign: TextAlign . center ,
style: const TextStyle (
fontFamily: ' SourceSerif4 ' ,
fontSize: 14 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ,
const SizedBox ( height: 24 ) ,
// Illustration
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 34 ) ,
child: ClipRRect (
borderRadius: BorderRadius . circular ( 56 ) ,
child: Image . asset (
' assets/images/about_find_agent.jpg ' ,
height: 241 ,
width: double . infinity ,
fit: BoxFit . cover ,
) ,
) ,
) ,
const SizedBox ( height: 24 ) ,
// Find Agents Now button
GestureDetector (
onTap: ( ) = > context . push ( ' /agents/search ' ) ,
child: Container (
height: 50 ,
width: 210 ,
decoration: BoxDecoration (
color: AppColors . accentOrange ,
borderRadius: BorderRadius . circular ( 25 ) ,
) ,
alignment: Alignment . center ,
child: Text (
cta . buttonText ,
style: const TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 16 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ,
) ,
const SizedBox ( height: 12 ) ,
// Get Help button
GestureDetector (
onTap: ( ) = > context . push ( ' /contact ' ) ,
child: Container (
height: 50 ,
width: 210 ,
decoration: BoxDecoration (
borderRadius: BorderRadius . circular ( 25 ) ,
border: Border . all (
color: AppColors . primaryDark ,
width: 1 ,
) ,
) ,
alignment: Alignment . center ,
child: const Text (
' Get Help ' ,
style: TextStyle (
fontFamily: ' Fractul ' ,
fontSize: 16 ,
fontWeight: FontWeight . w700 ,
color: AppColors . primaryDark ,
) ,
) ,
) ,
) ,
] ,
) ;
}
}
class _TeamMemberPlaceholder extends StatelessWidget {
const _TeamMemberPlaceholder ( ) ;
@ override
Widget build ( BuildContext context ) {
return Container (
color: const Color ( 0xFFC4D9D4 ) ,
child: const Center (
child: Icon ( Icons . person , size: 60 , color: AppColors . primaryDark ) ,
) ,
) ;
}
}