update address

This commit is contained in:
Phuoc Nguyen
2025-11-18 17:04:00 +07:00
parent a5eb95fa64
commit 0dda402246
33 changed files with 4250 additions and 232 deletions

View File

@@ -0,0 +1,221 @@
/// 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');
}