222 lines
6.4 KiB
Dart
222 lines
6.4 KiB
Dart
/// Address Provider
|
|
///
|
|
/// Riverpod providers for address management.
|
|
library;
|
|
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:worker/core/network/dio_client.dart';
|
|
import 'package:worker/features/account/data/datasources/address_remote_datasource.dart';
|
|
import 'package:worker/features/account/data/repositories/address_repository_impl.dart';
|
|
import 'package:worker/features/account/domain/entities/address.dart';
|
|
import 'package:worker/features/account/domain/repositories/address_repository.dart';
|
|
|
|
part 'address_provider.g.dart';
|
|
|
|
// ============================================================================
|
|
// DATASOURCE PROVIDER
|
|
// ============================================================================
|
|
|
|
/// Provides instance of AddressRemoteDataSource
|
|
@riverpod
|
|
Future<AddressRemoteDataSource> addressRemoteDataSource(Ref ref) async {
|
|
final dioClient = await ref.watch(dioClientProvider.future);
|
|
return AddressRemoteDataSource(dioClient.dio);
|
|
}
|
|
|
|
// ============================================================================
|
|
// REPOSITORY PROVIDER
|
|
// ============================================================================
|
|
|
|
/// Provides instance of AddressRepository
|
|
@riverpod
|
|
Future<AddressRepository> addressRepository(Ref ref) async {
|
|
final remoteDataSource =
|
|
await ref.watch(addressRemoteDataSourceProvider.future);
|
|
|
|
return AddressRepositoryImpl(
|
|
remoteDataSource: remoteDataSource,
|
|
);
|
|
}
|
|
|
|
// ============================================================================
|
|
// ADDRESSES LIST PROVIDER
|
|
// ============================================================================
|
|
|
|
/// Manages list of addresses with online-only approach
|
|
///
|
|
/// This is the MAIN provider for the addresses feature.
|
|
/// Returns list of Address entities from the API.
|
|
///
|
|
/// Online-only: Always fetches from API, no offline caching.
|
|
/// Uses keepAlive to prevent unnecessary reloads.
|
|
/// Provides refresh() method for pull-to-refresh functionality.
|
|
@Riverpod(keepAlive: true)
|
|
class Addresses extends _$Addresses {
|
|
late AddressRepository _repository;
|
|
|
|
@override
|
|
Future<List<Address>> build() async {
|
|
_repository = await ref.read(addressRepositoryProvider.future);
|
|
return await _loadAddresses();
|
|
}
|
|
|
|
// ==========================================================================
|
|
// PRIVATE METHODS
|
|
// ==========================================================================
|
|
|
|
/// Load addresses from repository
|
|
///
|
|
/// Online-only: Fetches from API
|
|
Future<List<Address>> _loadAddresses() async {
|
|
try {
|
|
final addresses = await _repository.getAddresses();
|
|
_debugPrint('Loaded ${addresses.length} addresses');
|
|
return addresses;
|
|
} catch (e) {
|
|
_debugPrint('Error loading addresses: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
// ==========================================================================
|
|
// PUBLIC METHODS
|
|
// ==========================================================================
|
|
|
|
/// Create new address
|
|
///
|
|
/// Calls API to create address, then refreshes the list.
|
|
Future<void> createAddress(Address address) async {
|
|
try {
|
|
_debugPrint('Creating address: ${address.addressTitle}');
|
|
|
|
await _repository.createAddress(address);
|
|
|
|
// Refresh the list after successful creation
|
|
await refresh();
|
|
|
|
_debugPrint('Successfully created address');
|
|
} catch (e) {
|
|
_debugPrint('Error creating address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Update existing address
|
|
///
|
|
/// Calls API to update address, then refreshes the list.
|
|
Future<void> updateAddress(Address address) async {
|
|
try {
|
|
_debugPrint('Updating address: ${address.name}');
|
|
|
|
await _repository.updateAddress(address);
|
|
|
|
// Refresh the list after successful update
|
|
await refresh();
|
|
|
|
_debugPrint('Successfully updated address');
|
|
} catch (e) {
|
|
_debugPrint('Error updating address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Delete address
|
|
///
|
|
/// Calls API to delete address, then refreshes the list.
|
|
Future<void> deleteAddress(String name) async {
|
|
try {
|
|
_debugPrint('Deleting address: $name');
|
|
|
|
await _repository.deleteAddress(name);
|
|
|
|
// Refresh the list after successful deletion
|
|
await refresh();
|
|
|
|
_debugPrint('Successfully deleted address');
|
|
} catch (e) {
|
|
_debugPrint('Error deleting address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Set address as default
|
|
///
|
|
/// Calls API to set address as default, then refreshes the list.
|
|
Future<void> setDefaultAddress(String name) async {
|
|
try {
|
|
_debugPrint('Setting default address: $name');
|
|
|
|
await _repository.setDefaultAddress(name);
|
|
|
|
// Refresh the list after successful update
|
|
await refresh();
|
|
|
|
_debugPrint('Successfully set default address');
|
|
} catch (e) {
|
|
_debugPrint('Error setting default address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Refresh addresses from API
|
|
///
|
|
/// Used for pull-to-refresh functionality.
|
|
/// Fetches latest data from API.
|
|
Future<void> refresh() async {
|
|
state = const AsyncValue.loading();
|
|
state = await AsyncValue.guard(() async {
|
|
return await _loadAddresses();
|
|
});
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// HELPER PROVIDERS
|
|
// ============================================================================
|
|
|
|
/// Get the default address
|
|
///
|
|
/// Derived from the addresses list.
|
|
/// Returns the address marked as default, or null if none.
|
|
@riverpod
|
|
Address? defaultAddress(Ref ref) {
|
|
final addressesAsync = ref.watch(addressesProvider);
|
|
|
|
return addressesAsync.when(
|
|
data: (addresses) {
|
|
try {
|
|
return addresses.firstWhere((addr) => addr.isDefault);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
},
|
|
loading: () => null,
|
|
error: (_, __) => null,
|
|
);
|
|
}
|
|
|
|
/// Get address count
|
|
///
|
|
/// Derived from the addresses list.
|
|
/// Returns the number of addresses.
|
|
@riverpod
|
|
int addressCount(Ref ref) {
|
|
final addressesAsync = ref.watch(addressesProvider);
|
|
|
|
return addressesAsync.when(
|
|
data: (addresses) => addresses.length,
|
|
loading: () => 0,
|
|
error: (_, __) => 0,
|
|
);
|
|
}
|
|
|
|
// ============================================================================
|
|
// DEBUG UTILITIES
|
|
// ============================================================================
|
|
|
|
/// Debug print helper
|
|
void _debugPrint(String message) {
|
|
// ignore: avoid_print
|
|
print('[AddressProvider] $message');
|
|
}
|