Files
sendico/frontend/pshared/lib/provider/payment/flow.dart

167 lines
4.7 KiB
Dart

import 'package:collection/collection.dart';
import 'package:flutter/foundation.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/recipient.dart';
import 'package:pshared/provider/recipient/provider.dart';
import 'package:pshared/provider/recipient/pmethods.dart';
class PaymentFlowProvider extends ChangeNotifier {
PaymentType _selectedType;
PaymentType? _preferredType;
PaymentMethodData? _manualPaymentData;
List<PaymentMethod> _recipientMethods = [];
Recipient? _recipient;
PaymentFlowProvider({
required PaymentType initialType,
PaymentType? preferredType,
}) : _selectedType = initialType,
_preferredType = preferredType ?? initialType;
PaymentType get selectedType => _selectedType;
PaymentMethodData? get manualPaymentData => _manualPaymentData;
Recipient? get recipient => _recipient;
PaymentMethod? get selectedMethod => hasRecipient
? _recipientMethods.firstWhereOrNull((method) => method.type == _selectedType)
: null;
bool get hasRecipient => _recipient != null;
MethodMap get availableTypes => hasRecipient
? _buildAvailableTypes(_recipientMethods)
: {for (final type in PaymentType.values) type: null};
PaymentMethodData? get selectedPaymentData =>
hasRecipient ? selectedMethod?.data : _manualPaymentData;
List<PaymentMethod> get methodsForRecipient => hasRecipient
? List<PaymentMethod>.unmodifiable(_recipientMethods)
: const [];
void update(
RecipientsProvider recipientsProvider,
PaymentMethodsProvider methodsProvider,
) =>
_applyState(
recipient: recipientsProvider.currentObject,
methods: methodsProvider.methodsForRecipient(recipientsProvider.currentObject),
preferredType: _preferredType,
forceResetManualData: false,
);
void selectType(PaymentType type, {bool resetManualData = false}) {
if (hasRecipient && !availableTypes.containsKey(type)) {
return;
}
if (_selectedType == type && (!resetManualData || _manualPaymentData == null)) {
return;
}
_selectedType = type;
if (resetManualData) {
_manualPaymentData = null;
}
notifyListeners();
}
void setManualPaymentData(PaymentMethodData? data) {
_manualPaymentData = data;
notifyListeners();
}
void setPreferredType(PaymentType? preferredType) {
if (_preferredType == preferredType) {
return;
}
_preferredType = preferredType;
_applyState(
recipient: _recipient,
methods: _recipientMethods,
preferredType: _preferredType,
forceResetManualData: false,
);
}
PaymentType _resolveSelectedType({
required Recipient? recipient,
required MethodMap availableTypes,
PaymentType? preferredType,
}) {
if (recipient == null) {
return preferredType ?? _selectedType;
}
if (availableTypes.isEmpty) {
return preferredType ?? PaymentType.bankAccount;
}
if (availableTypes.keys.contains(_selectedType)) {
return _selectedType;
}
if (preferredType != null && availableTypes.keys.contains(preferredType)) {
return preferredType;
}
return availableTypes.keys.first;
}
void _applyState({
required Recipient? recipient,
required List<PaymentMethod> methods,
required PaymentType? preferredType,
required bool forceResetManualData,
}) {
final availableTypes = _buildAvailableTypes(methods);
final resolvedType = _resolveSelectedType(
recipient: recipient,
availableTypes: availableTypes,
preferredType: preferredType,
);
var hasChanges = false;
if (_recipient != recipient) {
_recipient = recipient;
hasChanges = true;
}
if (!_hasSameMethods(methods)) {
_recipientMethods = methods;
hasChanges = true;
}
if (resolvedType != _selectedType) {
_selectedType = resolvedType;
hasChanges = true;
}
if ((recipient != null || forceResetManualData) && _manualPaymentData != null) {
_manualPaymentData = null;
hasChanges = true;
}
if (hasChanges) notifyListeners();
}
MethodMap _buildAvailableTypes(List<PaymentMethod> methods) => {
for (final method in methods) method.type: method.data,
};
bool _hasSameMethods(List<PaymentMethod> methods) {
if (_recipientMethods.length != methods.length) return false;
for (var i = 0; i < methods.length; i++) {
final current = _recipientMethods[i];
final next = methods[i];
if (current.id != next.id || current.updatedAt != next.updatedAt) return false;
}
return true;
}
}