From de4a7b80405c2d29ad3df8d423a60c4e8fda769c Mon Sep 17 00:00:00 2001 From: pradeepkumar Date: Sat, 14 Mar 2026 23:52:45 +0530 Subject: [PATCH] feat: Implement pull-to-refresh functionality on the agent detail screen by adding a refresh method to the provider and integrating a RefreshIndicator. --- .../presentation/screens/about_screen.dart | 35 ++++++++++++------- .../providers/agent_detail_provider.dart | 18 ++++++++++ .../screens/agent_detail_screen.dart | 11 ++++-- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/lib/features/about/presentation/screens/about_screen.dart b/lib/features/about/presentation/screens/about_screen.dart index fe48692..bec583f 100644 --- a/lib/features/about/presentation/screens/about_screen.dart +++ b/lib/features/about/presentation/screens/about_screen.dart @@ -324,7 +324,7 @@ class AboutScreen extends ConsumerWidget { _buildBannerCaption(state.hero.bannerOverlayText), const SizedBox(height: 16), _buildStatsRow(state.stats), - const SizedBox(height: 32), + const SizedBox(height: 24), _buildSectionTitle(state.featuresBadge), const SizedBox(height: 12), _buildWhyChooseUsSubtitle(), @@ -333,11 +333,11 @@ class AboutScreen extends ConsumerWidget { padding: const EdgeInsets.only(bottom: 15), child: _buildFeatureCard(f), )), - const SizedBox(height: 25), + const SizedBox(height: 20), _buildTeamSection(context, ref, state), - const SizedBox(height: 40), + const SizedBox(height: 24), _buildCtaSection(context, state.cta), - const SizedBox(height: 30), + const SizedBox(height: 24), ], ), ); @@ -606,7 +606,7 @@ class AboutScreen extends ConsumerWidget { ), ), ), - const SizedBox(height: 40), + const SizedBox(height: 20), // Team carousel SizedBox( height: 330, @@ -640,7 +640,7 @@ class AboutScreen extends ConsumerWidget { child: SizedBox( height: 211, width: double.infinity, - child: _buildTeamMemberImage(member.imageUrl), + child: _buildTeamMemberImage(member.imageUrl, index), ), ), ), @@ -717,10 +717,19 @@ class AboutScreen extends ConsumerWidget { } // -- Team member image (handles asset://, S3 keys, and URLs) -- - Widget _buildTeamMemberImage(String imageUrl) { - const placeholder = _TeamMemberPlaceholder(); + // Falls back to local professional-N.jpg assets when CMS image fails. + Widget _buildTeamMemberImage(String imageUrl, int index) { + // Local fallback asset based on index + final fallbackAsset = 'assets/images/professional-${index + 1}.jpg'; + Widget fallbackImage() => Image.asset( + fallbackAsset, + height: 211, + width: double.infinity, + fit: BoxFit.cover, + errorBuilder: (_, __, ___) => const _TeamMemberPlaceholder(), + ); - if (imageUrl.isEmpty) return placeholder; + if (imageUrl.isEmpty) return fallbackImage(); // Local asset images (defaults) if (imageUrl.startsWith('asset://')) { @@ -730,17 +739,17 @@ class AboutScreen extends ConsumerWidget { height: 211, width: double.infinity, fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) => placeholder, + errorBuilder: (_, __, ___) => fallbackImage(), ); } - // S3 key or URL from CMS + // S3 key or URL from CMS — fall back to local asset on error return S3Image( imageUrl: imageUrl, height: 211, fit: BoxFit.cover, - placeholder: (_) => placeholder, - errorWidget: (_) => placeholder, + placeholder: (_) => fallbackImage(), + errorWidget: (_) => fallbackImage(), ); } diff --git a/lib/features/agents/presentation/providers/agent_detail_provider.dart b/lib/features/agents/presentation/providers/agent_detail_provider.dart index b777b9e..c0498d9 100644 --- a/lib/features/agents/presentation/providers/agent_detail_provider.dart +++ b/lib/features/agents/presentation/providers/agent_detail_provider.dart @@ -399,6 +399,24 @@ class AgentDetailNotifier extends StateNotifier { } } + Future refresh() async { + try { + final results = await Future.wait([ + _repo.getAgentById(agentId), + _repo.getFieldValues(agentId), + _repo.getTestimonials(agentId), + ]); + state = state.copyWith( + agent: results[0] as AgentProfile, + fieldValues: results[1] as List, + testimonials: results[2] as List>, + isLoading: false, + ); + // Also refresh connection status + await loadConnectionStatus(); + } catch (_) {} + } + Future loadConnectionStatus() async { final status = await _repo.getConnectionStatus(agentId); state = state.copyWith(connectionStatus: status); diff --git a/lib/features/agents/presentation/screens/agent_detail_screen.dart b/lib/features/agents/presentation/screens/agent_detail_screen.dart index b3caf07..4e0af20 100644 --- a/lib/features/agents/presentation/screens/agent_detail_screen.dart +++ b/lib/features/agents/presentation/screens/agent_detail_screen.dart @@ -92,8 +92,14 @@ class _AgentDetailScreenState extends ConsumerState { Widget _buildContent(AgentDetailState state) { final agent = state.agent!; - return SingleChildScrollView( - child: Column( + return RefreshIndicator( + color: AppColors.accentOrange, + onRefresh: () => ref + .read(agentDetailProvider(widget.agentId).notifier) + .refresh(), + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( children: [ // ── Avatar Section ── const SizedBox(height: 16), @@ -132,6 +138,7 @@ class _AgentDetailScreenState extends ConsumerState { const SizedBox(height: 30), ], ), + ), ); }