refactoring for recipient addition page
This commit is contained in:
@@ -1,22 +1,16 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/models/recipient/status.dart';
|
||||
import 'package:pshared/models/recipient/type.dart';
|
||||
import 'package:pshared/provider/recipient/methods_cache.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
|
||||
import 'package:pweb/pages/address_book/form/view.dart';
|
||||
import 'package:pweb/services/posthog.dart';
|
||||
import 'package:pweb/utils/error/snackbar.dart';
|
||||
import 'package:pweb/pages/address_book/form/body.dart';
|
||||
import 'package:pweb/providers/address_book_recipient_form.dart';
|
||||
import 'package:pweb/utils/payment/availability.dart';
|
||||
import 'package:pweb/utils/payment/label.dart';
|
||||
import 'package:pweb/utils/snackbar.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
@@ -35,11 +29,8 @@ class _AddressBookRecipientFormState extends State<AddressBookRecipientForm> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
late TextEditingController _nameCtrl;
|
||||
late TextEditingController _emailCtrl;
|
||||
RecipientType _type = RecipientType.internal;
|
||||
RecipientStatus _status = RecipientStatus.ready;
|
||||
final MethodMap _methods = {};
|
||||
late RecipientMethodsCacheProvider _methodsCacheProvider;
|
||||
bool _hasInitializedMethods = false;
|
||||
|
||||
static const List<PaymentType> _supportedTypes = visiblePaymentTypes;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -47,129 +38,60 @@ class _AddressBookRecipientFormState extends State<AddressBookRecipientForm> {
|
||||
final r = widget.recipient;
|
||||
_nameCtrl = TextEditingController(text: r?.name ?? '');
|
||||
_emailCtrl = TextEditingController(text: r?.email ?? '');
|
||||
_type = r?.type ?? RecipientType.internal;
|
||||
_status = r?.status ?? RecipientStatus.ready;
|
||||
_methodsCacheProvider = context.read<RecipientMethodsCacheProvider>()
|
||||
..addListener(_onProviderChanged);
|
||||
if (r != null) {
|
||||
_methodsCacheProvider.refreshRecipient(r.id);
|
||||
_syncMethodsFromCache();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Recipient?> _doSave() async {
|
||||
final recipients = context.read<RecipientsProvider>();
|
||||
final recipient = widget.recipient == null
|
||||
? await recipients.create(
|
||||
name: _nameCtrl.text,
|
||||
email: _emailCtrl.text,
|
||||
)
|
||||
: widget.recipient!;
|
||||
recipients.setCurrentObject(recipient.id);
|
||||
final methods = <PaymentType, PaymentMethodData>{};
|
||||
final names = <PaymentType, String>{};
|
||||
for (final entry in _methods.entries) {
|
||||
final data = entry.value;
|
||||
if (data == null) continue;
|
||||
methods[entry.key] = data;
|
||||
names[entry.key] = getPaymentTypeLabel(context, entry.key);
|
||||
}
|
||||
await _methodsCacheProvider.syncRecipientMethods(
|
||||
recipientId: recipient.id,
|
||||
methods: methods,
|
||||
names: names,
|
||||
);
|
||||
return recipient;
|
||||
}
|
||||
Map<PaymentType, String> _methodNames(BuildContext context) => {
|
||||
for (final type in _supportedTypes) type: getPaymentTypeLabel(context, type),
|
||||
};
|
||||
|
||||
Future<void> _save() async {
|
||||
Future<void> _save(AddressBookRecipientFormProvider formState) async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
|
||||
if (!_formKey.currentState!.validate()) {
|
||||
notifyUser(context, l10n.recipientFormValidationError);
|
||||
if (!_formKey.currentState!.validate() || !formState.hasAnyMethod) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(l10n.recipientFormRule)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_methods.isEmpty) {
|
||||
notifyUser(context, l10n.recipientFormRule);
|
||||
return;
|
||||
try {
|
||||
final saved = await formState.save(
|
||||
name: _nameCtrl.text,
|
||||
email: _emailCtrl.text,
|
||||
methodNames: _methodNames(context),
|
||||
);
|
||||
widget.onSaved?.call(saved);
|
||||
} catch (_) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(l10n.notificationError(l10n.noErrorInformation))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unawaited(PosthogService.recipientAddCompleted(
|
||||
_type,
|
||||
_status,
|
||||
_methods.keys.toSet(),
|
||||
));
|
||||
final recipient = await executeActionWithNotification(
|
||||
context: context,
|
||||
action: _doSave,
|
||||
errorMessage: l10n.errorSaveRecipient,
|
||||
successMessage: l10n.recipientSavedSuccessfully,
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProxyProvider2<
|
||||
RecipientsProvider,
|
||||
RecipientMethodsCacheProvider,
|
||||
AddressBookRecipientFormProvider
|
||||
>(
|
||||
create: (_) => AddressBookRecipientFormProvider(
|
||||
recipient: widget.recipient,
|
||||
supportedTypes: _supportedTypes,
|
||||
),
|
||||
update: (_, recipientsProvider, methodsCache, formProvider) =>
|
||||
formProvider!..updateProviders(
|
||||
recipientsProvider: recipientsProvider,
|
||||
methodsCache: methodsCache,
|
||||
),
|
||||
child: AddressBookRecipientFormBody(
|
||||
formKey: _formKey,
|
||||
nameCtrl: _nameCtrl,
|
||||
emailCtrl: _emailCtrl,
|
||||
isEditing: widget.recipient != null,
|
||||
onSave: _save,
|
||||
onBack: () => widget.onSaved?.call(null),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
widget.onSaved?.call(recipient);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_methodsCacheProvider.removeListener(_onProviderChanged);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onProviderChanged() => _syncMethodsFromCache();
|
||||
|
||||
void _syncMethodsFromCache() {
|
||||
final recipient = widget.recipient;
|
||||
if (recipient == null || _hasInitializedMethods) return;
|
||||
if (!_methodsCacheProvider.hasMethodsFor(recipient.id)) return;
|
||||
final list = _methodsCacheProvider.methodsForRecipient(recipient.id);
|
||||
if (list.isEmpty) {
|
||||
_hasInitializedMethods = true;
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_methods
|
||||
..clear()
|
||||
..addEntries(list.map((m) {
|
||||
final data = switch (m.type) {
|
||||
PaymentType.card => m.cardData,
|
||||
PaymentType.iban => m.ibanData,
|
||||
PaymentType.wallet => m.walletData,
|
||||
PaymentType.bankAccount => m.bankAccountData,
|
||||
PaymentType.externalChain => m.cryptoAddressData,
|
||||
//TODO: support new payment methods
|
||||
_ => throw UnimplementedError('Payment method ${m.type} is not supported yet'),
|
||||
};
|
||||
return MapEntry(m.type, data);
|
||||
}));
|
||||
_hasInitializedMethods = true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => FormView(
|
||||
formKey: _formKey,
|
||||
nameCtrl: _nameCtrl,
|
||||
emailCtrl: _emailCtrl,
|
||||
type: _type,
|
||||
status: _status,
|
||||
methods: _methods,
|
||||
onTypeChanged: (t) => setState(() => _type = t),
|
||||
onStatusChanged: (s) => setState(() => _status = s),
|
||||
onMethodsChanged: (type, data) {
|
||||
setState(() {
|
||||
if (data != null) {
|
||||
_methods[type] = data;
|
||||
} else {
|
||||
_methods.remove(type);
|
||||
}
|
||||
});
|
||||
},
|
||||
onSave: _save,
|
||||
isEditing: widget.recipient != null,
|
||||
onBack: () {
|
||||
widget.onSaved?.call(null);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user