update address
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/// Address Repository Implementation
|
||||
///
|
||||
/// Implements address repository with online-only API calls.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/account/data/datasources/address_remote_datasource.dart';
|
||||
import 'package:worker/features/account/data/models/address_model.dart';
|
||||
import 'package:worker/features/account/domain/entities/address.dart';
|
||||
import 'package:worker/features/account/domain/repositories/address_repository.dart';
|
||||
|
||||
/// Address Repository Implementation
|
||||
///
|
||||
/// Online-only implementation - all operations go directly to API.
|
||||
/// No local caching or offline support.
|
||||
class AddressRepositoryImpl implements AddressRepository {
|
||||
final AddressRemoteDataSource _remoteDataSource;
|
||||
|
||||
AddressRepositoryImpl({
|
||||
required AddressRemoteDataSource remoteDataSource,
|
||||
}) : _remoteDataSource = remoteDataSource;
|
||||
|
||||
@override
|
||||
Future<List<Address>> getAddresses({bool? isDefault}) async {
|
||||
_debugPrint('Getting addresses...');
|
||||
|
||||
try {
|
||||
final addressModels = await _remoteDataSource.getAddresses(
|
||||
isDefault: isDefault,
|
||||
);
|
||||
|
||||
final addresses = addressModels.map((model) => model.toEntity()).toList();
|
||||
|
||||
_debugPrint('Retrieved ${addresses.length} addresses');
|
||||
return addresses;
|
||||
} catch (e) {
|
||||
_debugPrint('Error getting addresses: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Address> createAddress(Address address) async {
|
||||
_debugPrint('Creating address: ${address.addressTitle}');
|
||||
|
||||
try {
|
||||
// Create model with empty name (API will generate)
|
||||
final addressModel = AddressModel.fromEntity(address).copyWith(
|
||||
name: '', // Empty name indicates creation
|
||||
);
|
||||
|
||||
final savedModel = await _remoteDataSource.saveAddress(addressModel);
|
||||
|
||||
_debugPrint('Address created: ${savedModel.name}');
|
||||
return savedModel.toEntity();
|
||||
} catch (e) {
|
||||
_debugPrint('Error creating address: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Address> updateAddress(Address address) async {
|
||||
_debugPrint('Updating address: ${address.name}');
|
||||
|
||||
try {
|
||||
final addressModel = AddressModel.fromEntity(address);
|
||||
final savedModel = await _remoteDataSource.saveAddress(addressModel);
|
||||
|
||||
_debugPrint('Address updated: ${savedModel.name}');
|
||||
return savedModel.toEntity();
|
||||
} catch (e) {
|
||||
_debugPrint('Error updating address: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteAddress(String name) async {
|
||||
_debugPrint('Deleting address: $name');
|
||||
|
||||
try {
|
||||
await _remoteDataSource.deleteAddress(name);
|
||||
_debugPrint('Address deleted: $name');
|
||||
} catch (e) {
|
||||
_debugPrint('Error deleting address: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setDefaultAddress(String name) async {
|
||||
_debugPrint('Setting default address: $name');
|
||||
|
||||
try {
|
||||
// Get all addresses
|
||||
final addresses = await getAddresses();
|
||||
|
||||
// Find the address to set as default
|
||||
final targetAddress = addresses.firstWhere(
|
||||
(addr) => addr.name == name,
|
||||
orElse: () => throw Exception('Address not found: $name'),
|
||||
);
|
||||
|
||||
// Update the target address to be default
|
||||
await updateAddress(targetAddress.copyWith(isDefault: true));
|
||||
|
||||
// Update other addresses to not be default
|
||||
for (final addr in addresses) {
|
||||
if (addr.name != name && addr.isDefault) {
|
||||
await updateAddress(addr.copyWith(isDefault: false));
|
||||
}
|
||||
}
|
||||
|
||||
_debugPrint('Default address set: $name');
|
||||
} catch (e) {
|
||||
_debugPrint('Error setting default address: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Debug print helper
|
||||
void _debugPrint(String message) {
|
||||
// ignore: avoid_print
|
||||
print('[AddressRepository] $message');
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension to create a copy with modifications (since AddressModel is not freezed)
|
||||
extension _AddressModelCopyWith on AddressModel {
|
||||
AddressModel copyWith({
|
||||
String? name,
|
||||
String? addressTitle,
|
||||
String? addressLine1,
|
||||
String? phone,
|
||||
String? email,
|
||||
String? fax,
|
||||
String? taxCode,
|
||||
String? cityCode,
|
||||
String? wardCode,
|
||||
bool? isDefault,
|
||||
String? cityName,
|
||||
String? wardName,
|
||||
}) {
|
||||
return AddressModel(
|
||||
name: name ?? this.name,
|
||||
addressTitle: addressTitle ?? this.addressTitle,
|
||||
addressLine1: addressLine1 ?? this.addressLine1,
|
||||
phone: phone ?? this.phone,
|
||||
email: email ?? this.email,
|
||||
fax: fax ?? this.fax,
|
||||
taxCode: taxCode ?? this.taxCode,
|
||||
cityCode: cityCode ?? this.cityCode,
|
||||
wardCode: wardCode ?? this.wardCode,
|
||||
isDefault: isDefault ?? this.isDefault,
|
||||
cityName: cityName ?? this.cityName,
|
||||
wardName: wardName ?? this.wardName,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/// Location Repository Implementation
|
||||
///
|
||||
/// Implements location repository with offline-first strategy.
|
||||
library;
|
||||
|
||||
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/domain/entities/city.dart';
|
||||
import 'package:worker/features/account/domain/entities/ward.dart';
|
||||
import 'package:worker/features/account/domain/repositories/location_repository.dart';
|
||||
|
||||
/// Location Repository Implementation
|
||||
///
|
||||
/// Offline-first implementation:
|
||||
/// - Cities: Cache in Hive, fetch from API if cache is empty or force refresh
|
||||
/// - Wards: Cache per city, fetch from API if not cached or force refresh
|
||||
class LocationRepositoryImpl implements LocationRepository {
|
||||
final LocationRemoteDataSource _remoteDataSource;
|
||||
final LocationLocalDataSource _localDataSource;
|
||||
|
||||
LocationRepositoryImpl({
|
||||
required LocationRemoteDataSource remoteDataSource,
|
||||
required LocationLocalDataSource localDataSource,
|
||||
}) : _remoteDataSource = remoteDataSource,
|
||||
_localDataSource = localDataSource;
|
||||
|
||||
@override
|
||||
Future<List<City>> getCities({bool forceRefresh = false}) async {
|
||||
try {
|
||||
// Check cache first (offline-first)
|
||||
if (!forceRefresh && _localDataSource.hasCities()) {
|
||||
final cachedCities = _localDataSource.getCities();
|
||||
if (cachedCities.isNotEmpty) {
|
||||
return cachedCities.map((model) => model.toEntity()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
final cityModels = await _remoteDataSource.getCities();
|
||||
|
||||
// Save to cache
|
||||
await _localDataSource.saveCities(cityModels);
|
||||
|
||||
return cityModels.map((model) => model.toEntity()).toList();
|
||||
} catch (e) {
|
||||
// Fallback to cache on error
|
||||
if (!forceRefresh) {
|
||||
final cachedCities = _localDataSource.getCities();
|
||||
if (cachedCities.isNotEmpty) {
|
||||
return cachedCities.map((model) => model.toEntity()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Ward>> getWards(
|
||||
String cityCode, {
|
||||
bool forceRefresh = false,
|
||||
}) async {
|
||||
try {
|
||||
// Check cache first (offline-first)
|
||||
if (!forceRefresh && _localDataSource.hasWards(cityCode)) {
|
||||
final cachedWards = _localDataSource.getWards(cityCode);
|
||||
if (cachedWards.isNotEmpty) {
|
||||
return cachedWards.map((model) => model.toEntity()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
final wardModels = await _remoteDataSource.getWards(cityCode);
|
||||
|
||||
// Save to cache
|
||||
await _localDataSource.saveWards(cityCode, wardModels);
|
||||
|
||||
return wardModels.map((model) => model.toEntity()).toList();
|
||||
} catch (e) {
|
||||
// Fallback to cache on error
|
||||
if (!forceRefresh) {
|
||||
final cachedWards = _localDataSource.getWards(cityCode);
|
||||
if (cachedWards.isNotEmpty) {
|
||||
return cachedWards.map((model) => model.toEntity()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearCache() async {
|
||||
await _localDataSource.clearAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user