171 lines
5.3 KiB
Dart
171 lines
5.3 KiB
Dart
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();
|
|
}
|
|
}
|