Can i Select Multiple Accounts in a Banking app and pay them different amounts at the same time in flutter?

Issue

import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:money_formatter/money_formatter.dart';
import 'package:shukela_app/api/banking_app_api.dart';
import 'package:shukela_app/screens/stokvel_detail.dart';
import 'package:shukela_app/screens/stokvels.dart';
import 'package:shukela_app/utils/constants.dart';
import 'package:shukela_app/utils/global_variables.dart';
import 'package:sizer/sizer.dart';
import 'package:shukela_app/model/bankingapp_model.dart';

import '../utils/user_preferences.dart';

class PayMultipleStokvelScreen extends StatefulWidget {
  const PayMultipleStokvelScreen({Key? key}) : super(key: key);

  @override
  State<PayMultipleStokvelScreen> createState() =>
      _PayMultipleStokvelScreenState();
}

TextEditingController txtSearch = TextEditingController();
TextEditingController txtAmount = TextEditingController();

class _PayMultipleStokvelScreenState extends State<PayMultipleStokvelScreen> {
  String? selectedType;
  bool hasText = false;

  String buttonText = "PAY NOW";
  bool isLoading = false;

  Widget? showHideIcon() {
    if (hasText) {
      return IconButton(
        icon: const Icon(
          Icons.clear,
          color: AppColors.primaryBlue,
        ),
        onPressed: () {
          txtSearch.clear();
          setState(() {
            hasText = false;
          });
        },
      );
    } else {
      return null;
    }
  }

//   void _showMultiSelectDialog(BuildContext context) async {
//   await showDialog(
//     context: context,
//     builder: (ctx) {
//       return  MultiSelectDialog(
//         items: _animals.map((e) => MultiSelectItem(e, e)).toList(),
//         initialValue: _selectedAnimals,
//         onConfirm: (values) {...},
//       );
//     },
//   );
// }

  double? balance;

  final _formKey = GlobalKey<FormState>();

  var selectedValue;

  List<StokvelDetail> selectedStokvel = [];

  @override
  void initState() {
    super.initState();

    balance = double.parse(UserPreferences.getBalance() ?? '');
  }

  mf() {
    MoneyFormatter mf = MoneyFormatter(amount: balance!);
    return mf;
  }

  StokvelListState currentState = StokvelListState.showAllListState;

  @override
  Widget build(BuildContext context) => KeyboardDismisser(
        gestures: const [GestureType.onTap],
        child: SafeArea(
          child: Scaffold(
            backgroundColor: AppColors.secondaryColor,
            appBar: AppBar(
              backgroundColor: AppColors.secondaryColor,
              elevation: 0,
              title: const Text('Pay Multiple Stokvel',
                  style: screenTitleTextStyle),
              leading: IconButton(
                icon: const Icon(
                  Icons.arrow_back_ios,
                  color: AppColors.primaryBlue,
                ),
                onPressed: () => Navigator.pop(context),
              ),
            ),
            body: Form(
              key: _formKey,
              child: Column(
                children: [
                  SizedBox(height: 5.h),
                  Container(
                    height: 6.h,
                    width: 98.w,
                    padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                    child: TypeAheadFormField<Stokvel?>(
                      debounceDuration: const Duration(milliseconds: 500),
                      hideSuggestionsOnKeyboardHide: false,
                      suggestionsBoxDecoration: const SuggestionsBoxDecoration(
                          constraints: BoxConstraints(maxHeight: 450),
                          color: AppColors.secondaryColor,
                          borderRadius: BorderRadius.all(Radius.circular(10))),
                      textFieldConfiguration: TextFieldConfiguration(
                        style: const TextStyle(
                          color: AppColors.primaryBlue,
                          fontSize: 15.0,
                          fontWeight: FontWeight.bold,
                        ),
                        controller: txtSearch,
                        onChanged: (value) {
                          setState(() {
                            hasText = true;
                          });
                        },
                        decoration: InputDecoration(
                          prefixIcon: const Icon(
                            Icons.search,
                            color: AppColors.primaryBlue,
                          ),
                          suffixIcon: showHideIcon(),
                          hintText: 'Search Stokvel',
                          border: const OutlineInputBorder(
                            borderSide:
                                BorderSide(color: AppColors.primaryBlue),
                          ),
                          enabledBorder: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(4.0),
                            borderSide:
                                const BorderSide(color: AppColors.primaryBlue),
                          ),
                        ),
                      ),
                      validator: (val) {
                        if (val!.isEmpty) {
                          return "Please select stokvel";
                        }
                        return null;
                      },
                      suggestionsCallback: BankingAppApi.getStokvelSuggestions,
                      itemBuilder: (context, Stokvel? suggestion) {
                        final stokvel = suggestion!;

                        //
                        return ListTile(
                          trailing: SizedBox(
                            height: 20.0,
                            width: 20.0,
                            child: Container(
                              color: AppColors.primaryBlue,
                            ),
                          ),
                          title: Text(
                            stokvel.stokvelName!,
                            style: const TextStyle(
                              fontFamily: Fonts.primaryFont,
                              fontWeight: FontWeight.bold,
                              color: AppColors.primaryBlue,
                            ),
                          ),
                          subtitle: Text(
                            stokvel.stokvelType!,
                            style: const TextStyle(
                                fontFamily: Fonts.primaryFont,
                                fontWeight: FontWeight.bold,
                                color: AppColors.primaryBlue),
                          ),
                        );
                      },
                      noItemsFoundBuilder: (context) => const SizedBox(
                        height: 60,
                        child: Center(
                          child: Text(
                            'No Stokvel Found.',
                            style: TextStyle(fontSize: 20),
                          ),
                        ),
                      ),
                      onSuggestionSelected: (Stokvel? suggestion) {
                        final stokvel = suggestion!;
                        setState(() {
                          txtSearch.text = stokvel.stokvelName!;
                          hasText = true;
                        });
                        stokvelID = stokvel.stokvelID;
                        memberID = stokvel.memberID;
                      },
                    ),
                  ),

                  SizedBox(
                    height: 4.h,
                  ),
                  SizedBox(height: 3.h),
                  Container(
                    height: 6.h,
                    width: 98.w,
                    padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                    child: TextFormField(
                      controller: txtAmount,
                      decoration: const InputDecoration(
                        labelStyle: TextStyle(
                          color: AppColors.primaryBlue,
                          fontSize: 20.0,
                          fontWeight: FontWeight.bold,
                        ),
                        suffixText: "ZAR",
                        border: OutlineInputBorder(
                            borderSide:
                                BorderSide(color: AppColors.primaryBlue)),
                        focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.all(Radius.circular(4)),
                          borderSide: BorderSide(
                              width: 1, color: AppColors.primaryBlue),
                        ),
                        enabledBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.all(Radius.circular(4)),
                          borderSide: BorderSide(
                              width: 1, color: AppColors.primaryBlue),
                        ),
                        labelText: 'Amount',
                        contentPadding:
                            EdgeInsets.only(left: 20, right: 15, bottom: 8),
                      ),
                      keyboardType: TextInputType.number,
                      style: const TextStyle(
                          fontSize: 20.0,
                          fontFamily: Fonts.primaryFont,
                          color: AppColors.primaryBlue),
                      validator: (val) {
                        if (val!.isEmpty) {
                          return "Please enter amount";
                        }
                        return null;
                      },
                    ),
                  ),
                  SizedBox(height: 3.h),
                  Container(
                    height: 6.h,
                    width: 98.w,
                    padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                    child: TextField(
                      readOnly: true,
                      style: const TextStyle(
                          fontSize: 18.0, fontWeight: FontWeight.bold),
                      textAlign: TextAlign.center,
                      decoration: InputDecoration(
                        hintText: "Wallet Balance : R " + mf().output.nonSymbol,
                        border: const OutlineInputBorder(
                            borderSide:
                                BorderSide(color: AppColors.primaryBlue),
                            borderRadius: BorderRadius.horizontal()),
                        focusedBorder: const OutlineInputBorder(
                          borderRadius: BorderRadius.all(Radius.circular(4)),
                          borderSide: BorderSide(
                              width: 1, color: AppColors.primaryBlue),
                        ),
                        enabledBorder: const OutlineInputBorder(
                          borderRadius: BorderRadius.all(Radius.circular(4)),
                          borderSide: BorderSide(
                              width: 1, color: AppColors.primaryBlue),
                        ),
                      ),
                    ),
                  ),
                  SizedBox(height: 3.h),
                  Container(
                    height: 50,
                    width: 400,
                    padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                    child: ElevatedButton(
                      style: ButtonStyle(
                          backgroundColor:
                              MaterialStateProperty.all(Colors.white)),
                      child: isLoading
                          ? Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: const [
                                CircularProgressIndicator(
                                    color: AppColors.secondaryColor),
                                SizedBox(width: 24),
                                Text(
                                  "Submitting payment...",
                                  style: TextStyle(
                                      color: AppColors.secondaryColor),
                                )
                              ],
                            )
                          : Text(
                              buttonText,
                              style: const TextStyle(
                                  fontFamily: Fonts.primaryFont,
                                  fontWeight: FontWeight.bold,
                                  color: AppColors.primaryBlue),
                            ),
                      onPressed: () {
                        if (_formKey.currentState!.validate()) {
                          if (double.parse(txtAmount.text) <= balance!) {
                            setState(
                              () {
                                isLoading = true;
                              },
                            );
                            stokvelTransact.amount =
                                double.parse(txtAmount.text);
                            stokvelTransact.memberID = memberID;
                            stokvelTransact.stokvelID = stokvelID;
                            stokvelTransact.transactionTypeID = 1;
                            api
                                .stokvelDeposit(stokvelTransact,
                                    "StokvelTransaction/StokvelTransact")
                                .then(
                                  (value) => setState(
                                    () {
                                      Future.delayed(
                                          const Duration(seconds: 3));
                                      isLoading = false;
                                      if (value == "Success") {
                                        ScaffoldMessenger.of(context)
                                            .showSnackBar(snackBar(
                                                content:
                                                    'Payment made succesfully',
                                                duration: 5));
                                      } else {
                                        ScaffoldMessenger.of(context)
                                            .showSnackBar(snackBar(
                                                content:
                                                    'We have encountered technical problems, Try again later',
                                                duration: 5));
                                      }
                                    },
                                  ),
                                )
                                .catchError(
                              (err) {
                                setState(() {
                                  isLoading = false;
                                });
                                ScaffoldMessenger.of(context).showSnackBar(
                                    snackBar(
                                        content: err.toString(), duration: 7));
                              },
                            );
                          } else {
                            ScaffoldMessenger.of(context).showSnackBar(snackBar(
                                content: "Insuficient funds!", duration: 7));
                          }
                        }
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      );
}

The above code is for the single page that I want to achieve this

This is what I want to achieve or any suggestions are accepted, I want to mark the Group of Stokvels I want to pay and pay them different accounts I don’t know if it’s possible please I’m new in flutter it a project I have to get it done as soon as possible this is the source code for my whole payment page, for now, I’m able to pay a single Stokvel Group but I want to select multiple

This is my Payment Page for a single payment for single Group on the shown Image.

Solution

I highly suggest starting with formatting of the current code – its hard to read and with that hard to maintain.

The simple idea would be:

  • use List<StokvelDetail> selectedStokvel = []; you created to add the Stokvel’s in every time you select Stokvel in SearchBar

  • Add Map<int,double> amounts = {}; <StokvelId, amount> to keep track of the amount you want to send to each Stokvel

  • Based on selectedStokvel build multiple ‘amount window’ widgets

  • Before submit verify walletBalance >= amounts.values.reduce((a,b)=> a + b)

  • For each selectedStokvel call api.stokvelDeposit(stokvelTransact, ...

I would primarly focus on spliting this code to multiple Widget classes, there are many schools but I like to have around 150 lines of code in single file at most.

From what i see your file can be easily split into:

Column(
    children: [
        SizedBox(),
        SearchBar(),
        SizedBox(),
        AmountInput(), --> StokvelAmountInput() for each selectedStokvel
        SizedBox(),
        WalletBalance(),
        SizedBox(),
        SubmitButton(),
    ]),
    ```

Answered By – Jan-Stepien

Answer Checked By – Timothy Miller (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.