feat: Implement dynamic top professionals section with agent/lender tabs using Riverpod for state management.
This commit is contained in:
129
lib/features/agents/presentation/providers/agents_provider.dart
Normal file
129
lib/features/agents/presentation/providers/agents_provider.dart
Normal file
@@ -0,0 +1,129 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:real_estate_mobile/features/agents/data/agents_repository.dart';
|
||||
import 'package:real_estate_mobile/features/agents/data/models/agent_profile.dart';
|
||||
import 'package:real_estate_mobile/features/agents/data/models/agent_type.dart';
|
||||
|
||||
// Repository provider
|
||||
final agentsRepositoryProvider = Provider<AgentsRepository>((ref) {
|
||||
return AgentsRepository();
|
||||
});
|
||||
|
||||
// Agent types provider
|
||||
final agentTypesProvider = FutureProvider<List<AgentType>>((ref) async {
|
||||
final repository = ref.watch(agentsRepositoryProvider);
|
||||
return repository.getAgentTypes();
|
||||
});
|
||||
|
||||
// Top professionals state
|
||||
class TopProfessionalsState {
|
||||
final List<AgentProfile> agents;
|
||||
final List<AgentProfile> lenders;
|
||||
final List<AgentType> agentTypes;
|
||||
final bool isLoading;
|
||||
final String? error;
|
||||
final String activeTab; // 'agents' or 'lenders'
|
||||
|
||||
const TopProfessionalsState({
|
||||
this.agents = const [],
|
||||
this.lenders = const [],
|
||||
this.agentTypes = const [],
|
||||
this.isLoading = false,
|
||||
this.error,
|
||||
this.activeTab = 'agents',
|
||||
});
|
||||
|
||||
TopProfessionalsState copyWith({
|
||||
List<AgentProfile>? agents,
|
||||
List<AgentProfile>? lenders,
|
||||
List<AgentType>? agentTypes,
|
||||
bool? isLoading,
|
||||
String? error,
|
||||
String? activeTab,
|
||||
}) {
|
||||
return TopProfessionalsState(
|
||||
agents: agents ?? this.agents,
|
||||
lenders: lenders ?? this.lenders,
|
||||
agentTypes: agentTypes ?? this.agentTypes,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
error: error,
|
||||
activeTab: activeTab ?? this.activeTab,
|
||||
);
|
||||
}
|
||||
|
||||
List<AgentProfile> get activeList =>
|
||||
activeTab == 'agents' ? agents : lenders;
|
||||
}
|
||||
|
||||
class TopProfessionalsNotifier extends StateNotifier<TopProfessionalsState> {
|
||||
final AgentsRepository _repository;
|
||||
|
||||
TopProfessionalsNotifier(this._repository)
|
||||
: super(const TopProfessionalsState()) {
|
||||
_loadData();
|
||||
}
|
||||
|
||||
Future<void> _loadData() async {
|
||||
state = state.copyWith(isLoading: true, error: null);
|
||||
|
||||
try {
|
||||
// Fetch agent types first to find agent/lender type IDs
|
||||
final agentTypes = await _repository.getAgentTypes();
|
||||
state = state.copyWith(agentTypes: agentTypes);
|
||||
|
||||
// Find agent and lender type IDs
|
||||
String? agentTypeId;
|
||||
String? lenderTypeId;
|
||||
|
||||
for (final type in agentTypes) {
|
||||
final slug = type.slug.toLowerCase();
|
||||
if (slug.contains('agent')) {
|
||||
agentTypeId = type.id;
|
||||
} else if (slug.contains('lender')) {
|
||||
lenderTypeId = type.id;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch agents and lenders in parallel
|
||||
final results = await Future.wait([
|
||||
_repository.searchAgents(
|
||||
agentTypeId: agentTypeId,
|
||||
limit: 10,
|
||||
sortBy: 'averageRating',
|
||||
sortOrder: 'desc',
|
||||
),
|
||||
_repository.searchAgents(
|
||||
agentTypeId: lenderTypeId,
|
||||
limit: 10,
|
||||
sortBy: 'averageRating',
|
||||
sortOrder: 'desc',
|
||||
),
|
||||
]);
|
||||
|
||||
state = state.copyWith(
|
||||
agents: results[0].data,
|
||||
lenders: results[1].data,
|
||||
isLoading: false,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
error: 'Failed to load professionals',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void setActiveTab(String tab) {
|
||||
state = state.copyWith(activeTab: tab);
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
await _loadData();
|
||||
}
|
||||
}
|
||||
|
||||
final topProfessionalsProvider =
|
||||
StateNotifierProvider<TopProfessionalsNotifier, TopProfessionalsState>(
|
||||
(ref) {
|
||||
final repository = ref.watch(agentsRepositoryProvider);
|
||||
return TopProfessionalsNotifier(repository);
|
||||
});
|
||||
Reference in New Issue
Block a user