feat: implement FeaturedAgentItem model and update UI to sync with web CMS, and add form reset functionality to agent edit screen
This commit is contained in:
@@ -504,7 +504,23 @@ class _AgentEditProfileScreenState
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: _saving ? null : () => context.pop(),
|
onPressed: _saving ? null : () {
|
||||||
|
// Reset form to original values (reload from provider)
|
||||||
|
setState(() {
|
||||||
|
_formData.clear();
|
||||||
|
_repeatableEntries.clear();
|
||||||
|
_initialized = false;
|
||||||
|
for (final c in _controllers) {
|
||||||
|
c.dispose();
|
||||||
|
}
|
||||||
|
_controllers.clear();
|
||||||
|
for (final c in _tagControllers.values) {
|
||||||
|
c.dispose();
|
||||||
|
}
|
||||||
|
_tagControllers.clear();
|
||||||
|
});
|
||||||
|
// Re-initialize will happen on next build via _initializeFormData
|
||||||
|
},
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
side: const BorderSide(color: AppColors.primaryDark),
|
side: const BorderSide(color: AppColors.primaryDark),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
|||||||
@@ -126,15 +126,46 @@ class HeroContent {
|
|||||||
|
|
||||||
// --- Features Section ---
|
// --- Features Section ---
|
||||||
|
|
||||||
|
class FeaturedAgentItem {
|
||||||
|
final String name;
|
||||||
|
final String role;
|
||||||
|
final String rating;
|
||||||
|
final String location;
|
||||||
|
final String experience;
|
||||||
|
final String imageUrl;
|
||||||
|
|
||||||
|
const FeaturedAgentItem({
|
||||||
|
this.name = '',
|
||||||
|
this.role = '',
|
||||||
|
this.rating = '',
|
||||||
|
this.location = '',
|
||||||
|
this.experience = '',
|
||||||
|
this.imageUrl = '',
|
||||||
|
});
|
||||||
|
|
||||||
|
factory FeaturedAgentItem.fromJson(Map<String, dynamic> json) {
|
||||||
|
return FeaturedAgentItem(
|
||||||
|
name: json['name'] as String? ?? '',
|
||||||
|
role: json['role'] as String? ?? '',
|
||||||
|
rating: json['rating'] as String? ?? '',
|
||||||
|
location: json['location'] as String? ?? '',
|
||||||
|
experience: json['experience'] as String? ?? '',
|
||||||
|
imageUrl: json['imageUrl'] as String? ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FeaturesContent {
|
class FeaturesContent {
|
||||||
final String title;
|
final String title;
|
||||||
final String subtitle;
|
final String subtitle;
|
||||||
final List<FeatureItem> features;
|
final List<FeatureItem> features;
|
||||||
|
final List<FeaturedAgentItem> featuredAgents;
|
||||||
|
|
||||||
const FeaturesContent({
|
const FeaturesContent({
|
||||||
this.title = '',
|
this.title = '',
|
||||||
this.subtitle = '',
|
this.subtitle = '',
|
||||||
this.features = const [],
|
this.features = const [],
|
||||||
|
this.featuredAgents = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
factory FeaturesContent.fromJson(Map<String, dynamic> json) {
|
factory FeaturesContent.fromJson(Map<String, dynamic> json) {
|
||||||
@@ -146,6 +177,11 @@ class FeaturesContent {
|
|||||||
(e) => FeatureItem.fromJson(e as Map<String, dynamic>))
|
(e) => FeatureItem.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
|
featuredAgents: (json['featuredAgents'] as List<dynamic>?)
|
||||||
|
?.map(
|
||||||
|
(e) => FeaturedAgentItem.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
[],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ class _FeaturedProfessionalsSectionState
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final homeState = ref.watch(homeProvider);
|
final homeState = ref.watch(homeProvider);
|
||||||
final cmsContent = homeState.content?.topProfessionals;
|
final featuresContent = homeState.content?.features;
|
||||||
|
|
||||||
// Use CMS agents list for the featured carousel
|
// Use CMS featuredAgents from features section (matches web)
|
||||||
final professionals = cmsContent?.agents ?? [];
|
final professionals = featuresContent?.featuredAgents ?? [];
|
||||||
|
|
||||||
if (homeState.isLoading) {
|
if (homeState.isLoading) {
|
||||||
return Padding(
|
return Padding(
|
||||||
@@ -140,7 +140,7 @@ class _FeaturedProfessionalsSectionState
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFeaturedCard(ProfessionalItem item, int index) {
|
Widget _buildFeaturedCard(FeaturedAgentItem item, int index) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@@ -185,10 +185,10 @@ class _FeaturedProfessionalsSectionState
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
|
|
||||||
// Subtitle
|
// Role
|
||||||
if (item.subtitle.isNotEmpty)
|
if (item.role.isNotEmpty)
|
||||||
Text(
|
Text(
|
||||||
item.subtitle,
|
item.role,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontFamily: 'Fractul',
|
fontFamily: 'Fractul',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
@@ -200,7 +200,7 @@ class _FeaturedProfessionalsSectionState
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
|
|
||||||
// Verified badge
|
// Verified badge + Rating
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
@@ -223,6 +223,20 @@ class _FeaturedProfessionalsSectionState
|
|||||||
color: Color(0xFF638559),
|
color: Color(0xFF638559),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (item.rating.isNotEmpty) ...[
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Icon(Icons.star, size: 16, color: Color(0xFFFFDE21)),
|
||||||
|
const SizedBox(width: 2),
|
||||||
|
Text(
|
||||||
|
'Rating',
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: 'SourceSerif4',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.primaryDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
|
|||||||
Reference in New Issue
Block a user