refactoring for recipient addition page
This commit is contained in:
170
frontend/pweb/lib/providers/address_book_recipient_form.dart
Normal file
170
frontend/pweb/lib/providers/address_book_recipient_form.dart
Normal file
@@ -0,0 +1,170 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:pshared/data/mapper/recipient/recipient.dart';
|
||||
import 'package:pshared/models/describable.dart';
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/methods/type.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/payment_method_draft.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/provider/recipient/methods_cache.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
|
||||
import 'package:pweb/models/seed_state.dart';
|
||||
|
||||
|
||||
class AddressBookRecipientFormProvider extends ChangeNotifier {
|
||||
RecipientMethodsCacheProvider? _methodsCache;
|
||||
RecipientsProvider? _recipientsProvider;
|
||||
final Recipient? _recipient;
|
||||
final List<PaymentType> _supportedTypes;
|
||||
|
||||
final Map<PaymentType, List<RecipientMethodDraft>> _methods;
|
||||
SeedState _seedState = SeedState.idle;
|
||||
|
||||
AddressBookRecipientFormProvider({
|
||||
required List<PaymentType> supportedTypes,
|
||||
Recipient? recipient,
|
||||
}) : _recipient = recipient,
|
||||
_supportedTypes = supportedTypes,
|
||||
_methods = {
|
||||
for (final type in supportedTypes) type: <RecipientMethodDraft>[],
|
||||
};
|
||||
|
||||
void updateProviders({
|
||||
required RecipientMethodsCacheProvider methodsCache,
|
||||
required RecipientsProvider recipientsProvider,
|
||||
}) {
|
||||
_recipientsProvider = recipientsProvider;
|
||||
if (identical(_methodsCache, methodsCache)) return;
|
||||
_methodsCache?.removeListener(_handleCacheChange);
|
||||
_methodsCache = methodsCache;
|
||||
_methodsCache?.addListener(_handleCacheChange);
|
||||
_maybeSeedFromCache();
|
||||
}
|
||||
|
||||
List<PaymentType> get supportedTypes => List.unmodifiable(_supportedTypes);
|
||||
Map<PaymentType, List<RecipientMethodDraft>> get methods => {
|
||||
for (final entry in _methods.entries)
|
||||
entry.key: List<RecipientMethodDraft>.unmodifiable(entry.value),
|
||||
};
|
||||
PaymentType? get preferredType =>
|
||||
_supportedTypes.firstWhere((type) => _methods[type]?.isNotEmpty == true, orElse: () => _supportedTypes.first);
|
||||
|
||||
bool get hasAnyMethod => _methods.values.any(
|
||||
(entries) => entries.any((entry) => entry.data != null || entry.existing != null),
|
||||
);
|
||||
|
||||
List<RecipientMethodDraft> allDrafts() =>
|
||||
_methods.values.expand((entries) => entries).toList();
|
||||
|
||||
int? addMethod(PaymentType type) {
|
||||
final entries = _methods[type];
|
||||
if (entries == null) return null;
|
||||
entries.add(RecipientMethodDraft(type: type));
|
||||
notifyListeners();
|
||||
return entries.length - 1;
|
||||
}
|
||||
|
||||
void removeMethod(PaymentType type, int index) {
|
||||
final entries = _methods[type];
|
||||
if (entries == null) return;
|
||||
if (index < 0 || index >= entries.length) return;
|
||||
entries.removeAt(index);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void updateMethod(PaymentType type, int index, PaymentMethodData data) {
|
||||
final entries = _methods[type];
|
||||
if (entries == null) return;
|
||||
if (index < 0 || index >= entries.length) return;
|
||||
entries[index].data = data;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _handleCacheChange() {
|
||||
_maybeSeedFromCache();
|
||||
}
|
||||
|
||||
void _maybeSeedFromCache() {
|
||||
final recipient = _recipient;
|
||||
final methodsCache = _methodsCache;
|
||||
if (recipient == null || methodsCache == null) return;
|
||||
if (_seedState == SeedState.seeded) return;
|
||||
if (!methodsCache.hasMethodsFor(recipient.id)) return;
|
||||
_seedState = SeedState.seeded;
|
||||
_seedMethodsFromExisting(methodsCache.methodsForRecipient(recipient.id));
|
||||
}
|
||||
|
||||
void _seedMethodsFromExisting(List<PaymentMethod> existing) {
|
||||
if (existing.isEmpty) return;
|
||||
final next = <PaymentType, List<RecipientMethodDraft>>{
|
||||
for (final type in _supportedTypes) type: <RecipientMethodDraft>[],
|
||||
};
|
||||
for (final method in existing) {
|
||||
final type = method.type;
|
||||
final entries = next[type];
|
||||
if (entries == null) continue;
|
||||
entries.add(
|
||||
RecipientMethodDraft(
|
||||
type: type,
|
||||
existing: method,
|
||||
data: method.data,
|
||||
),
|
||||
);
|
||||
}
|
||||
_methods
|
||||
..clear()
|
||||
..addAll(next);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<Recipient> save({
|
||||
required String name,
|
||||
required String email,
|
||||
required Map<PaymentType, String> methodNames,
|
||||
}) async {
|
||||
final recipientsProvider = _recipientsProvider;
|
||||
final methodsCache = _methodsCache;
|
||||
if (recipientsProvider == null || methodsCache == null) {
|
||||
throw StateError('Form provider dependencies are not set');
|
||||
}
|
||||
|
||||
final trimmedName = name.trim();
|
||||
final trimmedEmail = email.trim();
|
||||
|
||||
if (_recipient == null) {
|
||||
final created = await recipientsProvider.create(
|
||||
name: trimmedName,
|
||||
email: trimmedEmail,
|
||||
);
|
||||
await methodsCache.syncRecipientMethods(
|
||||
recipientId: created.id,
|
||||
methods: allDrafts(),
|
||||
names: methodNames,
|
||||
);
|
||||
return created;
|
||||
}
|
||||
|
||||
final updated = _recipient.copyWith(
|
||||
describable: newDescribable(
|
||||
name: trimmedName,
|
||||
description: _recipient.description,
|
||||
),
|
||||
email: trimmedEmail,
|
||||
);
|
||||
await recipientsProvider.update(updated.toDTO().toJson());
|
||||
await methodsCache.syncRecipientMethods(
|
||||
recipientId: updated.id,
|
||||
methods: allDrafts(),
|
||||
names: methodNames,
|
||||
);
|
||||
return updated;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_methodsCache?.removeListener(_handleCacheChange);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user