import 'package:amplitude_flutter/amplitude.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pweb/pages/dashboard/payouts/payment_form.dart'; import 'package:pweb/pages/dashboard/payouts/single/form/details.dart'; import 'package:pweb/pages/dashboard/payouts/single/form/header.dart'; import 'package:pweb/providers/payment_methods.dart'; import 'package:pweb/providers/recipient.dart'; import 'package:pweb/services/amplitude.dart'; import 'package:pweb/utils/dimensions.dart'; import 'package:pweb/utils/payment/dropdown.dart'; import 'package:pweb/utils/payment/selector_type.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; //TODO: decide whether to make AppDimensions universal for the whole app or leave it as it is - unique for this page alone class PaymentPage extends StatefulWidget { final PaymentType? type; final ValueChanged? onBack; const PaymentPage({super.key, this.type, this.onBack}); @override State createState() => _PaymentPageState(); } class _PaymentPageState extends State { late Map _availableTypes; late PaymentType _selectedType; bool _isFormVisible = false; @override void didChangeDependencies() { super.didChangeDependencies(); final recipientProvider = context.watch(); final methodsProvider = context.watch(); final recipient = recipientProvider.selectedRecipient; // Initialize available types based on whether we have a recipient if (recipient != null) { // We have a recipient - use their payment methods _availableTypes = { if (recipient.card != null) PaymentType.card: recipient.card!, if (recipient.iban != null) PaymentType.iban: recipient.iban!, if (recipient.wallet != null) PaymentType.wallet: recipient.wallet!, if (recipient.bank != null) PaymentType.bankAccount: recipient.bank!, }; // Set selected type if it's available, otherwise use first available type if (_availableTypes.containsKey(_selectedType)) { // Keep current selection if valid } else if (_availableTypes.isNotEmpty) { _selectedType = _availableTypes.keys.first; } else { // Fallback if recipient has no payment methods _selectedType = PaymentType.bankAccount; } } else { // No recipient - we're creating a new payment from scratch _availableTypes = {}; _selectedType = widget.type ?? PaymentType.bankAccount; _isFormVisible = true; // Always show form when creating new payment } // Load payment methods if not already loaded if (methodsProvider.methods.isEmpty && !methodsProvider.isLoading) { WidgetsBinding.instance.addPostFrameCallback((_) { methodsProvider.loadMethods(); }); } } @override void initState() { super.initState(); // Initial values _availableTypes = {}; _selectedType = widget.type ?? PaymentType.bankAccount; } @override Widget build(BuildContext context) { final theme = Theme.of(context); final dimensions = AppDimensions(); final recipientProvider = context.watch(); final methodsProvider = context.watch(); final recipient = recipientProvider.selectedRecipient; // Show loading state for payment methods if (methodsProvider.isLoading) { return const Center(child: CircularProgressIndicator()); } // Show error state for payment methods if (methodsProvider.error != null) { return Center( child: Text('Error: ${methodsProvider.error}'), ); } return Align( alignment: Alignment.topCenter, child: ConstrainedBox( constraints: BoxConstraints(maxWidth: dimensions.maxContentWidth), child: Material( elevation: dimensions.elevationSmall, borderRadius: BorderRadius.circular(dimensions.borderRadiusMedium), color: theme.colorScheme.onSecondary, child: Padding( padding: EdgeInsets.all(dimensions.paddingLarge), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Back button Align( alignment: Alignment.topLeft, child: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { widget.onBack?.call(recipient); }, ), ), SizedBox(height: dimensions.paddingSmall), // Header Row( children: [ Icon( Icons.send_rounded, color: theme.colorScheme.primary, size: dimensions.iconSizeLarge ), SizedBox(width: dimensions.spacingSmall), Text( AppLocalizations.of(context)!.sendTo, style: theme.textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold ), ), ], ), SizedBox(height: dimensions.paddingXXLarge), // Payment method dropdown (user's payment methods) PaymentMethodDropdown( methods: methodsProvider.methods, initialValue: methodsProvider.selectedMethod, onChanged: (method) { methodsProvider.selectMethod(method); }, ), SizedBox(height: dimensions.paddingXLarge), // Recipient section (only show if we have a recipient) if (recipient != null) ...[ RecipientHeader(recipient: recipient), SizedBox(height: dimensions.paddingMedium), // Payment type selector (recipient's payment methods) if (_availableTypes.isNotEmpty) PaymentTypeSelector( availableTypes: _availableTypes, selectedType: _selectedType, onSelected: (type) => setState(() => _selectedType = type), ), SizedBox(height: dimensions.paddingMedium), ], // Payment details section PaymentDetailsSection( isFormVisible: recipient == null || _isFormVisible, onToggle: recipient != null ? () => setState(() => _isFormVisible = !_isFormVisible) : null, // No toggle when creating new payment selectedType: _selectedType, data: _availableTypes[_selectedType], isEditable: recipient == null, ), const PaymentFormWidget(), SizedBox(height: dimensions.paddingXXXLarge), Center( child: SizedBox( width: dimensions.buttonWidth, height: dimensions.buttonHeight, child: InkWell( borderRadius: BorderRadius.circular(dimensions.borderRadiusSmall), onTap: () => // TODO: Handle Payment logic AmplitudeService.pageOpened(PayoutDestination.payment), //TODO: replace with payment event child: Container( decoration: BoxDecoration( color: theme.colorScheme.primary, borderRadius: BorderRadius.circular(dimensions.borderRadiusSmall), ), child: Center( child: Text( AppLocalizations.of(context)!.send, style: theme.textTheme.bodyLarge?.copyWith( color: theme.colorScheme.onSecondary, fontWeight: FontWeight.w600, ), ), ), ), ), ), ), SizedBox(height: dimensions.paddingLarge), ], ), ), ), ), ), ); } }