update address
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
/// Location Provider
|
||||
///
|
||||
/// Riverpod providers for cities and wards management.
|
||||
library;
|
||||
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:worker/core/database/hive_service.dart';
|
||||
import 'package:worker/core/network/dio_client.dart';
|
||||
import 'package:worker/features/account/data/datasources/location_local_datasource.dart';
|
||||
import 'package:worker/features/account/data/datasources/location_remote_datasource.dart';
|
||||
import 'package:worker/features/account/data/repositories/location_repository_impl.dart';
|
||||
import 'package:worker/features/account/domain/entities/city.dart';
|
||||
import 'package:worker/features/account/domain/entities/ward.dart';
|
||||
import 'package:worker/features/account/domain/repositories/location_repository.dart';
|
||||
|
||||
part 'location_provider.g.dart';
|
||||
|
||||
// ============================================================================
|
||||
// DATASOURCE PROVIDERS
|
||||
// ============================================================================
|
||||
|
||||
/// Provides instance of LocationRemoteDataSource
|
||||
@riverpod
|
||||
Future<LocationRemoteDataSource> locationRemoteDataSource(Ref ref) async {
|
||||
final dioClient = await ref.watch(dioClientProvider.future);
|
||||
return LocationRemoteDataSource(dioClient.dio);
|
||||
}
|
||||
|
||||
/// Provides instance of LocationLocalDataSource
|
||||
@riverpod
|
||||
LocationLocalDataSource locationLocalDataSource(Ref ref) {
|
||||
final hiveService = HiveService();
|
||||
return LocationLocalDataSource(hiveService);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// REPOSITORY PROVIDER
|
||||
// ============================================================================
|
||||
|
||||
/// Provides instance of LocationRepository
|
||||
@riverpod
|
||||
Future<LocationRepository> locationRepository(Ref ref) async {
|
||||
final remoteDataSource = await ref.watch(locationRemoteDataSourceProvider.future);
|
||||
final localDataSource = ref.watch(locationLocalDataSourceProvider);
|
||||
|
||||
return LocationRepositoryImpl(
|
||||
remoteDataSource: remoteDataSource,
|
||||
localDataSource: localDataSource,
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// CITIES PROVIDER
|
||||
// ============================================================================
|
||||
|
||||
/// Manages list of cities with offline-first approach
|
||||
///
|
||||
/// This is the MAIN provider for cities.
|
||||
/// Returns list of City entities (cached → API).
|
||||
@Riverpod(keepAlive: true)
|
||||
class Cities extends _$Cities {
|
||||
late LocationRepository _repository;
|
||||
|
||||
@override
|
||||
Future<List<City>> build() async {
|
||||
_repository = await ref.read(locationRepositoryProvider.future);
|
||||
return await _loadCities();
|
||||
}
|
||||
|
||||
/// Load cities (offline-first)
|
||||
Future<List<City>> _loadCities({bool forceRefresh = false}) async {
|
||||
try {
|
||||
final cities = await _repository.getCities(forceRefresh: forceRefresh);
|
||||
return cities;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Refresh cities from API
|
||||
Future<void> refresh() async {
|
||||
state = const AsyncValue.loading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
return await _loadCities(forceRefresh: true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WARDS PROVIDER (per city)
|
||||
// ============================================================================
|
||||
|
||||
/// Manages list of wards for a specific city with offline-first approach
|
||||
///
|
||||
/// Uses .family modifier to create a provider per city code.
|
||||
/// Returns list of Ward entities (cached → API).
|
||||
@riverpod
|
||||
Future<List<Ward>> wards(Ref ref, String cityCode) async {
|
||||
final repository = await ref.watch(locationRepositoryProvider.future);
|
||||
|
||||
try {
|
||||
final wards = await repository.getWards(cityCode);
|
||||
return wards;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// HELPER PROVIDERS
|
||||
// ============================================================================
|
||||
|
||||
/// Get city by code
|
||||
@riverpod
|
||||
City? cityByCode(Ref ref, String code) {
|
||||
final citiesAsync = ref.watch(citiesProvider);
|
||||
|
||||
return citiesAsync.when(
|
||||
data: (cities) {
|
||||
try {
|
||||
return cities.firstWhere((city) => city.code == code);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
loading: () => null,
|
||||
error: (_, __) => null,
|
||||
);
|
||||
}
|
||||
|
||||
/// Get cities as map (code → City) for easy lookup
|
||||
@riverpod
|
||||
Map<String, City> citiesMap(Ref ref) {
|
||||
final citiesAsync = ref.watch(citiesProvider);
|
||||
|
||||
return citiesAsync.when(
|
||||
data: (cities) => {for (final city in cities) city.code: city},
|
||||
loading: () => {},
|
||||
error: (_, __) => {},
|
||||
);
|
||||
}
|
||||
|
||||
/// Get wards as map (code → Ward) for a city
|
||||
@riverpod
|
||||
Map<String, Ward> wardsMap(Ref ref, String cityCode) {
|
||||
final wardsAsync = ref.watch(wardsProvider(cityCode));
|
||||
|
||||
return wardsAsync.when(
|
||||
data: (wards) => {for (final ward in wards) ward.code: ward},
|
||||
loading: () => {},
|
||||
error: (_, __) => {},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user