Merge pull request 'Finally Fixed search field in payment page and cleaned up payment flow' (#204) from SEND020 into main
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/ledger Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/mntx_gateway Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/ledger Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/mntx_gateway Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
Reviewed-on: #204
This commit was merged in pull request #204.
This commit is contained in:
@@ -13,15 +13,18 @@ import 'package:pshared/provider/permissions.dart';
|
||||
import 'package:pshared/provider/account.dart';
|
||||
import 'package:pshared/provider/organizations.dart';
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
import 'package:pshared/provider/payment/provider.dart';
|
||||
import 'package:pshared/provider/payment/quotation.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
import 'package:pshared/provider/recipient/pmethods.dart';
|
||||
import 'package:pshared/provider/payment/wallets.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/service/payment/wallets.dart';
|
||||
|
||||
import 'package:pweb/app/app.dart';
|
||||
import 'package:pweb/app/timeago.dart';
|
||||
import 'package:pweb/providers/carousel.dart';
|
||||
import 'package:pweb/providers/mock_payment.dart';
|
||||
import 'package:pweb/providers/operatioins.dart';
|
||||
import 'package:pweb/providers/two_factor.dart';
|
||||
import 'package:pweb/providers/upload_history.dart';
|
||||
@@ -89,8 +92,12 @@ void main() async {
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => WalletTransactionsProvider(MockWalletTransactionsService())..load(),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => MockPaymentProvider(),
|
||||
ChangeNotifierProxyProvider2<RecipientsProvider, PaymentMethodsProvider, PaymentFlowProvider>(
|
||||
create: (_) => PaymentFlowProvider(initialType: PaymentType.bankAccount),
|
||||
update: (context, recipients, methods, provider) => provider!..update(
|
||||
recipients,
|
||||
methods,
|
||||
),
|
||||
),
|
||||
|
||||
ChangeNotifierProvider(
|
||||
@@ -99,6 +106,18 @@ void main() async {
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => PaymentAmountProvider(),
|
||||
),
|
||||
ChangeNotifierProxyProvider6<OrganizationsProvider, PaymentAmountProvider, WalletsProvider, PaymentFlowProvider, RecipientsProvider, PaymentMethodsProvider, QuotationProvider>(
|
||||
create: (_) => QuotationProvider(),
|
||||
update: (_, organization, payment, wallet, flow, recipients, methods, provider) =>
|
||||
provider!..update(organization, payment, wallet, flow, recipients, methods),
|
||||
),
|
||||
ChangeNotifierProxyProvider2<OrganizationsProvider, QuotationProvider, PaymentProvider>(
|
||||
create: (_) => PaymentProvider(),
|
||||
update: (context, organization, quotation, provider) => provider!..update(
|
||||
organization,
|
||||
quotation,
|
||||
),
|
||||
),
|
||||
],
|
||||
child: const PayApp(),
|
||||
),
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
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/methods/type.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/provider/organizations.dart';
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
import 'package:pshared/provider/payment/provider.dart';
|
||||
import 'package:pshared/provider/payment/quotation.dart';
|
||||
import 'package:pshared/provider/recipient/pmethods.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pweb/pages/payment_methods/payment_page/body.dart';
|
||||
import 'package:pshared/provider/payment/wallets.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/payment_page/body.dart';
|
||||
import 'package:pweb/widgets/sidebar/destinations.dart';
|
||||
import 'package:pweb/services/posthog.dart';
|
||||
|
||||
@@ -60,30 +52,23 @@ class _PaymentPageState extends State<PaymentPage> {
|
||||
}
|
||||
|
||||
void _initializePaymentPage() {
|
||||
final methodsProvider = context.read<PaymentMethodsProvider>();
|
||||
_handleWalletAutoSelection(methodsProvider);
|
||||
final flowProvider = context.read<PaymentFlowProvider>();
|
||||
flowProvider.setPreferredType(widget.initialPaymentType);
|
||||
}
|
||||
|
||||
void _handleSearchChanged(String query) {
|
||||
context.read<RecipientsProvider>().setQuery(query);
|
||||
}
|
||||
|
||||
void _handleRecipientSelected(BuildContext context, Recipient recipient) {
|
||||
void _handleRecipientSelected(Recipient recipient) {
|
||||
final recipientProvider = context.read<RecipientsProvider>();
|
||||
recipientProvider.setCurrentObject(recipient.id);
|
||||
_clearSearchField();
|
||||
}
|
||||
|
||||
void _handleRecipientCleared(BuildContext context) {
|
||||
void _handleRecipientCleared() {
|
||||
final recipientProvider = context.read<RecipientsProvider>();
|
||||
final methodsProvider = context.read<PaymentMethodsProvider>();
|
||||
|
||||
recipientProvider.setCurrentObject(null);
|
||||
context.read<PaymentFlowProvider>().reset(
|
||||
recipient: null,
|
||||
availableTypes: _availablePaymentTypes(null, methodsProvider),
|
||||
preferredType: widget.initialPaymentType,
|
||||
);
|
||||
_clearSearchField();
|
||||
}
|
||||
|
||||
@@ -93,107 +78,42 @@ class _PaymentPageState extends State<PaymentPage> {
|
||||
context.read<RecipientsProvider>().setQuery('');
|
||||
}
|
||||
|
||||
void _handleSendPayment(BuildContext context) {
|
||||
if (context.read<QuotationProvider>().isReady) {
|
||||
context.read<PaymentProvider>().pay();
|
||||
PosthogService.paymentInitiated(
|
||||
method: context.read<PaymentFlowProvider>().selectedType,
|
||||
void _handleSendPayment() {
|
||||
final flowProvider = context.read<PaymentFlowProvider>();
|
||||
final paymentProvider = context.read<PaymentProvider>();
|
||||
if (paymentProvider.isLoading) return;
|
||||
|
||||
paymentProvider.pay().then((_) {
|
||||
PosthogService.paymentInitiated(method: flowProvider.selectedType);
|
||||
}).catchError((error) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(error.toString())),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final methodsProvider = context.watch<PaymentMethodsProvider>();
|
||||
final recipientProvider = context.watch<RecipientsProvider>();
|
||||
final recipient = recipientProvider.currentObject;
|
||||
final availableTypes = _availablePaymentTypes(recipient, methodsProvider);
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProxyProvider2<RecipientsProvider, PaymentMethodsProvider, PaymentFlowProvider>(
|
||||
create: (_) => PaymentFlowProvider(
|
||||
initialType: widget.initialPaymentType ?? PaymentType.bankAccount,
|
||||
),
|
||||
update: (_, recipients, methods, flow) {
|
||||
final currentRecipient = recipients.currentObject;
|
||||
flow!.sync(
|
||||
recipient: currentRecipient,
|
||||
availableTypes: _availablePaymentTypes(currentRecipient, methods),
|
||||
preferredType: currentRecipient != null ? widget.initialPaymentType : null,
|
||||
);
|
||||
return flow;
|
||||
},
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => PaymentAmountProvider(),
|
||||
),
|
||||
ChangeNotifierProxyProvider6<OrganizationsProvider, PaymentAmountProvider, WalletsProvider, PaymentFlowProvider, RecipientsProvider, PaymentMethodsProvider, QuotationProvider>(
|
||||
create: (_) => QuotationProvider(),
|
||||
update: (_, organization, payment, wallet, flow, recipients, methods, provider) =>
|
||||
provider!..update(organization, payment, wallet, flow, recipients, methods),
|
||||
),
|
||||
ChangeNotifierProxyProvider2<OrganizationsProvider, QuotationProvider, PaymentProvider>(
|
||||
create: (_) => PaymentProvider(),
|
||||
update: (_, organization, quotation, provider) => provider!..update(organization, quotation),
|
||||
),
|
||||
],
|
||||
child: Builder(
|
||||
builder: (innerContext) => PaymentPageBody(
|
||||
onBack: widget.onBack,
|
||||
fallbackDestination: widget.fallbackDestination,
|
||||
recipient: recipient,
|
||||
recipientProvider: recipientProvider,
|
||||
methodsProvider: methodsProvider,
|
||||
availablePaymentTypes: availableTypes,
|
||||
searchController: _searchController,
|
||||
searchFocusNode: _searchFocusNode,
|
||||
onSearchChanged: _handleSearchChanged,
|
||||
onRecipientSelected: (selected) => _handleRecipientSelected(innerContext, selected),
|
||||
onRecipientCleared: () => _handleRecipientCleared(innerContext),
|
||||
onSend: () => _handleSendPayment(innerContext),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleWalletAutoSelection(PaymentMethodsProvider methodsProvider) {
|
||||
final wallet = context.read<WalletsProvider>().selectedWallet;
|
||||
if (wallet == null) return;
|
||||
|
||||
final matchingMethod = _getPaymentMethodForWallet(wallet, methodsProvider);
|
||||
if (matchingMethod != null) {
|
||||
methodsProvider.setCurrentObject(matchingMethod.id);
|
||||
}
|
||||
}
|
||||
|
||||
MethodMap _availablePaymentTypes(
|
||||
Recipient? recipient,
|
||||
PaymentMethodsProvider methodsProvider,
|
||||
) {
|
||||
if (recipient == null || !methodsProvider.isReady) return {};
|
||||
|
||||
final methodsForRecipient = methodsProvider.methods.where(
|
||||
(method) => !method.isArchived && method.recipientRef == recipient.id,
|
||||
final recipientProvider = context.read<RecipientsProvider>();
|
||||
final recipient = context.select<RecipientsProvider, Recipient?>(
|
||||
(provider) => provider.currentObject,
|
||||
);
|
||||
|
||||
return {
|
||||
for (final method in methodsForRecipient) method.type: method.data,
|
||||
};
|
||||
}
|
||||
|
||||
PaymentMethod? _getPaymentMethodForWallet(
|
||||
Wallet wallet,
|
||||
PaymentMethodsProvider methodsProvider,
|
||||
) {
|
||||
if (methodsProvider.methods.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return methodsProvider.methods.firstWhereOrNull(
|
||||
(method) =>
|
||||
method.type == PaymentType.wallet &&
|
||||
(method.description?.contains(wallet.walletUserID) ?? false),
|
||||
return PaymentPageBody(
|
||||
onBack: widget.onBack,
|
||||
fallbackDestination: widget.fallbackDestination,
|
||||
recipient: recipient,
|
||||
recipientProvider: recipientProvider,
|
||||
methodsProvider: methodsProvider,
|
||||
onWalletSelected: context.read<WalletsProvider>().selectWallet,
|
||||
searchController: _searchController,
|
||||
searchFocusNode: _searchFocusNode,
|
||||
onSearchChanged: _handleSearchChanged,
|
||||
onRecipientSelected: _handleRecipientSelected,
|
||||
onRecipientCleared: _handleRecipientCleared,
|
||||
onSend: _handleSendPayment,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pshared/provider/recipient/pmethods.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
|
||||
@@ -17,7 +17,7 @@ class PaymentPageBody extends StatelessWidget {
|
||||
final Recipient? recipient;
|
||||
final RecipientsProvider recipientProvider;
|
||||
final PaymentMethodsProvider methodsProvider;
|
||||
final MethodMap availablePaymentTypes;
|
||||
final ValueChanged<Wallet> onWalletSelected;
|
||||
final PayoutDestination fallbackDestination;
|
||||
final TextEditingController searchController;
|
||||
final FocusNode searchFocusNode;
|
||||
@@ -32,7 +32,7 @@ class PaymentPageBody extends StatelessWidget {
|
||||
required this.recipient,
|
||||
required this.recipientProvider,
|
||||
required this.methodsProvider,
|
||||
required this.availablePaymentTypes,
|
||||
required this.onWalletSelected,
|
||||
required this.fallbackDestination,
|
||||
required this.searchController,
|
||||
required this.searchFocusNode,
|
||||
@@ -60,8 +60,7 @@ class PaymentPageBody extends StatelessWidget {
|
||||
onBack: onBack,
|
||||
recipient: recipient,
|
||||
recipientProvider: recipientProvider,
|
||||
methodsProvider: methodsProvider,
|
||||
availablePaymentTypes: availablePaymentTypes,
|
||||
onWalletSelected: onWalletSelected,
|
||||
fallbackDestination: fallbackDestination,
|
||||
searchController: searchController,
|
||||
searchFocusNode: searchFocusNode,
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/provider/recipient/pmethods.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/payment_page/back_button.dart';
|
||||
import 'package:pweb/pages/payment_methods/payment_page/header.dart';
|
||||
@@ -26,8 +22,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
final ValueChanged<Recipient?>? onBack;
|
||||
final Recipient? recipient;
|
||||
final RecipientsProvider recipientProvider;
|
||||
final PaymentMethodsProvider methodsProvider;
|
||||
final MethodMap availablePaymentTypes;
|
||||
final ValueChanged<Wallet> onWalletSelected;
|
||||
final PayoutDestination fallbackDestination;
|
||||
final TextEditingController searchController;
|
||||
final FocusNode searchFocusNode;
|
||||
@@ -41,8 +36,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
required this.onBack,
|
||||
required this.recipient,
|
||||
required this.recipientProvider,
|
||||
required this.methodsProvider,
|
||||
required this.availablePaymentTypes,
|
||||
required this.onWalletSelected,
|
||||
required this.fallbackDestination,
|
||||
required this.searchController,
|
||||
required this.searchFocusNode,
|
||||
@@ -55,7 +49,6 @@ class PaymentPageContent extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dimensions = AppDimensions();
|
||||
final flowProvider = context.watch<PaymentFlowProvider>();
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return Align(
|
||||
@@ -84,7 +77,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
SectionTitle(loc.sourceOfFunds),
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
PaymentMethodSelector(
|
||||
onMethodChanged: (m) => methodsProvider.setCurrentObject(m.id),
|
||||
onMethodChanged: onWalletSelected,
|
||||
),
|
||||
SizedBox(height: dimensions.paddingXLarge),
|
||||
RecipientSection(
|
||||
@@ -98,12 +91,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
onRecipientCleared: onRecipientCleared,
|
||||
),
|
||||
SizedBox(height: dimensions.paddingXLarge),
|
||||
PaymentInfoSection(
|
||||
dimensions: dimensions,
|
||||
flowProvider: flowProvider,
|
||||
recipient: recipient,
|
||||
availableTypes: availablePaymentTypes,
|
||||
),
|
||||
PaymentInfoSection(dimensions: dimensions),
|
||||
SizedBox(height: dimensions.paddingLarge),
|
||||
const PaymentFormWidget(),
|
||||
SizedBox(height: dimensions.paddingXXXLarge),
|
||||
|
||||
@@ -17,9 +17,11 @@ class PaymentMethodSelector extends StatelessWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Consumer<WalletsProvider>(builder:(context, provider, _) => PaymentMethodDropdown(
|
||||
methods: provider.wallets,
|
||||
initialValue: provider.selectedWallet,
|
||||
onChanged: onMethodChanged,
|
||||
));
|
||||
Widget build(BuildContext context) => Consumer<WalletsProvider>(
|
||||
builder: (context, provider, _) => PaymentMethodDropdown(
|
||||
methods: provider.wallets,
|
||||
selectedMethod: provider.selectedWallet,
|
||||
onChanged: onMethodChanged,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/provider/recipient/pmethods.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/form.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/payment_page/back_button.dart';
|
||||
import 'package:pweb/pages/payment_methods/payment_page/header.dart';
|
||||
import 'package:pweb/pages/payment_methods/payment_page/method_selector.dart';
|
||||
@@ -26,8 +22,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
final ValueChanged<Recipient?>? onBack;
|
||||
final Recipient? recipient;
|
||||
final RecipientsProvider recipientProvider;
|
||||
final PaymentMethodsProvider methodsProvider;
|
||||
final MethodMap availablePaymentTypes;
|
||||
final ValueChanged<Wallet> onWalletSelected;
|
||||
final PayoutDestination fallbackDestination;
|
||||
final TextEditingController searchController;
|
||||
final FocusNode searchFocusNode;
|
||||
@@ -41,8 +36,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
required this.onBack,
|
||||
required this.recipient,
|
||||
required this.recipientProvider,
|
||||
required this.methodsProvider,
|
||||
required this.availablePaymentTypes,
|
||||
required this.onWalletSelected,
|
||||
required this.fallbackDestination,
|
||||
required this.searchController,
|
||||
required this.searchFocusNode,
|
||||
@@ -55,7 +49,6 @@ class PaymentPageContent extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dimensions = AppDimensions();
|
||||
final flowProvider = context.watch<PaymentFlowProvider>();
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return Align(
|
||||
@@ -84,7 +77,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
SectionTitle(loc.sourceOfFunds),
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
PaymentMethodSelector(
|
||||
onMethodChanged: (m) => methodsProvider.setCurrentObject(m.id),
|
||||
onMethodChanged: onWalletSelected,
|
||||
),
|
||||
SizedBox(height: dimensions.paddingXLarge),
|
||||
RecipientSection(
|
||||
@@ -98,12 +91,7 @@ class PaymentPageContent extends StatelessWidget {
|
||||
onRecipientCleared: onRecipientCleared,
|
||||
),
|
||||
SizedBox(height: dimensions.paddingXLarge),
|
||||
PaymentInfoSection(
|
||||
dimensions: dimensions,
|
||||
flowProvider: flowProvider,
|
||||
recipient: recipient,
|
||||
availableTypes: availablePaymentTypes,
|
||||
),
|
||||
PaymentInfoSection(dimensions: dimensions),
|
||||
SizedBox(height: dimensions.paddingLarge),
|
||||
const PaymentFormWidget(),
|
||||
SizedBox(height: dimensions.paddingXXXLarge),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
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/provider/payment/flow.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/form.dart';
|
||||
@@ -15,25 +15,18 @@ import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
class PaymentInfoSection extends StatelessWidget {
|
||||
final AppDimensions dimensions;
|
||||
final MethodMap availableTypes;
|
||||
final PaymentFlowProvider flowProvider;
|
||||
final Recipient? recipient;
|
||||
|
||||
const PaymentInfoSection({
|
||||
super.key,
|
||||
required this.dimensions,
|
||||
required this.availableTypes,
|
||||
required this.flowProvider,
|
||||
required this.recipient,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final hasRecipient = recipient != null;
|
||||
final MethodMap resolvedAvailableTypes = hasRecipient
|
||||
? availableTypes
|
||||
: {for (final type in PaymentType.values) type: null};
|
||||
final flowProvider = context.watch<PaymentFlowProvider>();
|
||||
final hasRecipient = flowProvider.hasRecipient;
|
||||
final MethodMap resolvedAvailableTypes = flowProvider.availableTypes;
|
||||
|
||||
if (hasRecipient && resolvedAvailableTypes.isEmpty) {
|
||||
return Text(loc.recipientNoPaymentDetails);
|
||||
@@ -62,7 +55,7 @@ class PaymentInfoSection extends StatelessWidget {
|
||||
flowProvider.setManualPaymentData(data);
|
||||
}
|
||||
},
|
||||
initialData: hasRecipient ? resolvedAvailableTypes[selectedType] : flowProvider.manualPaymentData,
|
||||
initialData: flowProvider.selectedPaymentData,
|
||||
isEditable: !hasRecipient,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -45,25 +45,44 @@ class RecipientSection extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SectionTitle(loc.recipient),
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
RecipientSearchField(
|
||||
controller: searchController,
|
||||
onChanged: onSearchChanged,
|
||||
focusNode: searchFocusNode,
|
||||
),
|
||||
if (recipientProvider.query.isNotEmpty) ...[
|
||||
SizedBox(height: dimensions.paddingMedium),
|
||||
RecipientSearchResults(
|
||||
dimensions: dimensions,
|
||||
recipientProvider: recipientProvider,
|
||||
onRecipientSelected: onRecipientSelected,
|
||||
),
|
||||
],
|
||||
],
|
||||
return AnimatedBuilder(
|
||||
animation: recipientProvider,
|
||||
builder: (context, _) {
|
||||
final previousRecipient = recipientProvider.previousRecipient;
|
||||
final hasQuery = recipientProvider.query.isNotEmpty;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SectionTitle(loc.recipient),
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
RecipientSearchField(
|
||||
controller: searchController,
|
||||
onChanged: onSearchChanged,
|
||||
focusNode: searchFocusNode,
|
||||
),
|
||||
if (previousRecipient != null) ...[
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
ListTile(
|
||||
dense: true,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const Icon(Icons.undo),
|
||||
title: Text(loc.back),
|
||||
subtitle: Text(previousRecipient.name),
|
||||
onTap: () => onRecipientSelected(previousRecipient),
|
||||
),
|
||||
],
|
||||
if (hasQuery) ...[
|
||||
SizedBox(height: dimensions.paddingMedium),
|
||||
RecipientSearchResults(
|
||||
dimensions: dimensions,
|
||||
recipientProvider: recipientProvider,
|
||||
onRecipientSelected: onRecipientSelected,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,40 +8,27 @@ import 'package:pweb/pages/payment_methods/icon.dart';
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentMethodDropdown extends StatefulWidget {
|
||||
class PaymentMethodDropdown extends StatelessWidget {
|
||||
final List<Wallet> methods;
|
||||
final ValueChanged<Wallet> onChanged;
|
||||
final Wallet? initialValue;
|
||||
final Wallet? selectedMethod;
|
||||
|
||||
const PaymentMethodDropdown({
|
||||
super.key,
|
||||
required this.methods,
|
||||
required this.onChanged,
|
||||
this.initialValue,
|
||||
this.selectedMethod,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PaymentMethodDropdown> createState() => _PaymentMethodDropdownState();
|
||||
}
|
||||
|
||||
class _PaymentMethodDropdownState extends State<PaymentMethodDropdown> {
|
||||
late Wallet _selectedMethod;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedMethod = widget.initialValue ?? widget.methods.first;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => DropdownButtonFormField<Wallet>(
|
||||
dropdownColor: Theme.of(context).colorScheme.onSecondary,
|
||||
initialValue: _selectedMethod,
|
||||
value: _getSelectedMethod(),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context)!.whereGetMoney,
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
items: widget.methods.map((method) => DropdownMenuItem<Wallet>(
|
||||
items: methods.map((method) => DropdownMenuItem<Wallet>(
|
||||
value: method,
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -53,9 +40,14 @@ class _PaymentMethodDropdownState extends State<PaymentMethodDropdown> {
|
||||
)).toList(),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
setState(() => _selectedMethod = value);
|
||||
widget.onChanged(value);
|
||||
onChanged(value);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Wallet? _getSelectedMethod() {
|
||||
if (selectedMethod != null) return selectedMethod;
|
||||
if (methods.isEmpty) return null;
|
||||
return methods.first;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user