import 'package:flutter/material.dart'; import 'package:collection/collection.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/organizations.dart'; import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/provider/recipient/provider.dart'; import 'package:pweb/pages/address_book/form/view.dart'; import 'package:pweb/utils/error/snackbar.dart'; import 'package:pweb/utils/payment/label.dart'; import 'package:pweb/utils/snackbar.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; class AdressBookRecipientForm extends StatefulWidget { final Recipient? recipient; final ValueChanged? onSaved; const AdressBookRecipientForm({super.key, this.recipient, this.onSaved}); @override State createState() => _AdressBookRecipientFormState(); } class _AdressBookRecipientFormState extends State { final _formKey = GlobalKey(); late TextEditingController _nameCtrl; late TextEditingController _emailCtrl; RecipientType _type = RecipientType.internal; RecipientStatus _status = RecipientStatus.ready; final MethodMap _methods = {}; late PaymentMethodsProvider _methodsProvider; Future _loadMethods() async { _methodsProvider = PaymentMethodsProvider()..addListener(_onProviderChanged); await _methodsProvider.loadMethods( context.read(), widget.recipient?.id, ); for (final m in _methodsProvider.methods) { _methods[m.type] = 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'), }; } } @override void initState() { super.initState(); final r = widget.recipient; _nameCtrl = TextEditingController(text: r?.name ?? ''); _emailCtrl = TextEditingController(text: r?.email ?? ''); _type = r?.type ?? RecipientType.internal; _status = r?.status ?? RecipientStatus.ready; _loadMethods(); } Future _doSave() async { final recipients = context.read(); final methods = PaymentMethodsProvider(); final recipient = widget.recipient == null ? await recipients.create( name: _nameCtrl.text, email: _emailCtrl.text, ) : widget.recipient!; recipients.setCurrentObject(recipient.id); //TODO : redesign work with recipients / payment methods await methods.loadMethods(context.read(), recipient.id); for (final type in _methods.keys) { final data = _methods[type]!; final exising = methods.methods.firstWhereOrNull((m) => m.type == type); if (exising != null) { await methods.updateMethod(exising.copyWith(data: data)); } else { await methods.create( reacipientRef: recipient.id, name: getPaymentTypeLabel(context, type), data: data, ); } } return recipient; } //TODO: Change when registration is ready Future _save() async { if (!_formKey.currentState!.validate() || _methods.isEmpty) { notifyUser(context, AppLocalizations.of(context)!.errorSaveRecipient); return; } // AmplitudeService.recipientAddCompleted( // _type, // _status, // _methods.keys.toSet(), // ); final recipient = await executeActionWithNotification( context: context, action: _doSave, errorMessage: AppLocalizations.of(context)!.errorSaveRecipient, successMessage: AppLocalizations.of(context)!.recipientFormRule, ); widget.onSaved?.call(recipient); } @override void dispose() { _methodsProvider.removeListener(_onProviderChanged); _methodsProvider.dispose(); super.dispose(); } void _onProviderChanged() => setState(() {}); @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); }, ); }