feat: Implement pull-to-refresh functionality on the agent detail screen by adding a refresh method to the provider and integrating a RefreshIndicator.
This commit is contained in:
@@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -399,6 +399,24 @@ class AgentDetailNotifier extends StateNotifier<AgentDetailState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> 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<AgentFieldValue>,
|
||||
testimonials: results[2] as List<Map<String, dynamic>>,
|
||||
isLoading: false,
|
||||
);
|
||||
// Also refresh connection status
|
||||
await loadConnectionStatus();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Future<void> loadConnectionStatus() async {
|
||||
final status = await _repo.getConnectionStatus(agentId);
|
||||
state = state.copyWith(connectionStatus: status);
|
||||
|
||||
@@ -92,7 +92,13 @@ class _AgentDetailScreenState extends ConsumerState<AgentDetailScreen> {
|
||||
|
||||
Widget _buildContent(AgentDetailState state) {
|
||||
final agent = state.agent!;
|
||||
return SingleChildScrollView(
|
||||
return RefreshIndicator(
|
||||
color: AppColors.accentOrange,
|
||||
onRefresh: () => ref
|
||||
.read(agentDetailProvider(widget.agentId).notifier)
|
||||
.refresh(),
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
// ── Avatar Section ──
|
||||
@@ -132,6 +138,7 @@ class _AgentDetailScreenState extends ConsumerState<AgentDetailScreen> {
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user