feat: Implement agent search functionality and update the home screen to dynamically display professional data.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
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';
|
||||
import 'package:real_estate_mobile/features/agents/presentation/providers/agents_provider.dart';
|
||||
|
||||
class SearchAgentsState {
|
||||
final List<AgentProfile> agents;
|
||||
final List<AgentType> agentTypes;
|
||||
final bool isLoading;
|
||||
final bool isLoadingMore;
|
||||
final String? error;
|
||||
final String searchQuery;
|
||||
final String? selectedAgentTypeId;
|
||||
final int currentPage;
|
||||
final int totalPages;
|
||||
|
||||
const SearchAgentsState({
|
||||
this.agents = const [],
|
||||
this.agentTypes = const [],
|
||||
this.isLoading = false,
|
||||
this.isLoadingMore = false,
|
||||
this.error,
|
||||
this.searchQuery = '',
|
||||
this.selectedAgentTypeId,
|
||||
this.currentPage = 1,
|
||||
this.totalPages = 1,
|
||||
});
|
||||
|
||||
bool get hasMore => currentPage < totalPages;
|
||||
|
||||
SearchAgentsState copyWith({
|
||||
List<AgentProfile>? agents,
|
||||
List<AgentType>? agentTypes,
|
||||
bool? isLoading,
|
||||
bool? isLoadingMore,
|
||||
String? error,
|
||||
String? searchQuery,
|
||||
String? selectedAgentTypeId,
|
||||
bool clearAgentTypeId = false,
|
||||
int? currentPage,
|
||||
int? totalPages,
|
||||
}) {
|
||||
return SearchAgentsState(
|
||||
agents: agents ?? this.agents,
|
||||
agentTypes: agentTypes ?? this.agentTypes,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||
error: error,
|
||||
searchQuery: searchQuery ?? this.searchQuery,
|
||||
selectedAgentTypeId: clearAgentTypeId
|
||||
? null
|
||||
: (selectedAgentTypeId ?? this.selectedAgentTypeId),
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
totalPages: totalPages ?? this.totalPages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SearchAgentsNotifier extends StateNotifier<SearchAgentsState> {
|
||||
final AgentsRepository _repository;
|
||||
|
||||
SearchAgentsNotifier(this._repository)
|
||||
: super(const SearchAgentsState(isLoading: true)) {
|
||||
_init();
|
||||
}
|
||||
|
||||
Future<void> _init() async {
|
||||
try {
|
||||
final agentTypes = await _repository.getAgentTypes();
|
||||
state = state.copyWith(agentTypes: agentTypes);
|
||||
await _fetchAgents(page: 1);
|
||||
} catch (e) {
|
||||
state = state.copyWith(isLoading: false, error: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchAgents({required int page, bool append = false}) async {
|
||||
try {
|
||||
final response = await _repository.searchAgents(
|
||||
search: state.searchQuery.isNotEmpty ? state.searchQuery : null,
|
||||
agentTypeId: state.selectedAgentTypeId,
|
||||
page: page,
|
||||
limit: 10,
|
||||
);
|
||||
|
||||
state = state.copyWith(
|
||||
agents: append ? [...state.agents, ...response.data] : response.data,
|
||||
currentPage: response.page,
|
||||
totalPages: response.totalPages,
|
||||
isLoading: false,
|
||||
isLoadingMore: false,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
isLoadingMore: false,
|
||||
error: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void search(String query) {
|
||||
state = state.copyWith(
|
||||
searchQuery: query,
|
||||
isLoading: true,
|
||||
currentPage: 1,
|
||||
);
|
||||
_fetchAgents(page: 1);
|
||||
}
|
||||
|
||||
void filterByAgentType(String? agentTypeId) {
|
||||
state = state.copyWith(
|
||||
selectedAgentTypeId: agentTypeId,
|
||||
clearAgentTypeId: agentTypeId == null,
|
||||
isLoading: true,
|
||||
currentPage: 1,
|
||||
);
|
||||
_fetchAgents(page: 1);
|
||||
}
|
||||
|
||||
void loadMore() {
|
||||
if (state.isLoadingMore || !state.hasMore) return;
|
||||
state = state.copyWith(isLoadingMore: true);
|
||||
_fetchAgents(page: state.currentPage + 1, append: true);
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
state = state.copyWith(isLoading: true, currentPage: 1);
|
||||
await _fetchAgents(page: 1);
|
||||
}
|
||||
}
|
||||
|
||||
final searchAgentsProvider =
|
||||
StateNotifierProvider.autoDispose<SearchAgentsNotifier, SearchAgentsState>(
|
||||
(ref) {
|
||||
final repository = ref.watch(agentsRepositoryProvider);
|
||||
return SearchAgentsNotifier(repository);
|
||||
});
|
||||
Reference in New Issue
Block a user