maps/mobile/lib/features/search/providers/search_provider.dart
2026-03-31 21:01:08 +02:00

111 lines
2.8 KiB
Dart

import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/constants.dart';
import '../../../core/database/app_database.dart';
import '../data/search_repository.dart';
class SearchState {
final String query;
final List<SearchResult> results;
final List<SearchHistoryData> recentSearches;
final bool isLoading;
final String? error;
const SearchState({
this.query = '',
this.results = const [],
this.recentSearches = const [],
this.isLoading = false,
this.error,
});
SearchState copyWith({
String? query,
List<SearchResult>? results,
List<SearchHistoryData>? recentSearches,
bool? isLoading,
String? error,
bool clearError = false,
}) {
return SearchState(
query: query ?? this.query,
results: results ?? this.results,
recentSearches: recentSearches ?? this.recentSearches,
isLoading: isLoading ?? this.isLoading,
error: clearError ? null : (error ?? this.error),
);
}
}
class SearchNotifier extends Notifier<SearchState> {
late SearchRepository _repository;
Timer? _debounce;
@override
SearchState build() {
_repository = ref.watch(searchRepositoryProvider);
ref.onDispose(() => _debounce?.cancel());
Future.microtask(_loadHistory);
return const SearchState();
}
Future<void> _loadHistory() async {
final history = await _repository.getRecentSearches();
state = state.copyWith(recentSearches: history);
}
void updateQuery(String query) {
state = state.copyWith(query: query, clearError: true);
_debounce?.cancel();
if (query.trim().isEmpty) {
state = state.copyWith(results: [], isLoading: false);
return;
}
state = state.copyWith(isLoading: true);
_debounce = Timer(
const Duration(milliseconds: AppConstants.searchDebounceMs),
() => _performSearch(query),
);
}
Future<void> _performSearch(String query) async {
try {
final results = await _repository.search(query);
if (state.query == query) {
state = state.copyWith(results: results, isLoading: false);
}
} catch (e) {
state = state.copyWith(
isLoading: false,
error: 'Search failed. Please try again.',
);
}
}
Future<void> selectResult(SearchResult result) async {
await _repository.saveToHistory(
result.name,
lat: result.latitude,
lon: result.longitude,
);
await _loadHistory();
}
Future<void> deleteHistoryEntry(int id) async {
await _repository.deleteHistoryEntry(id);
await _loadHistory();
}
Future<void> clearHistory() async {
await _repository.clearHistory();
await _loadHistory();
}
}
final searchProvider =
NotifierProvider.autoDispose<SearchNotifier, SearchState>(
SearchNotifier.new,
);