From 88c776507ddb24e9b3c072f35bf22c98d7ec9051 Mon Sep 17 00:00:00 2001 From: Vusumuzi Khoza Date: Mon, 4 May 2026 00:06:52 +0200 Subject: [PATCH] implemented hotrecharge changes --- .vscode/launch.json | 10 ++ assets/.env.test | 3 +- lib/screens/home/home_controller.dart | 37 ++-- lib/screens/home/home_controller.freezed.dart | 46 ++--- lib/screens/home/home_controller.g.dart | 6 +- .../integration/integration_controller.dart | 31 ++-- lib/screens/pay/pay_screen.dart | 158 ++++++++++-------- 7 files changed, 170 insertions(+), 121 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index b8d2d84..2cf2908 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,5 +4,15 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "qpay", + "request": "launch", + "type": "dart", + "deviceId": "chrome", + "args": [ + "--dart-define=APP_ENV=test" + ] + }, + ] } \ No newline at end of file diff --git a/assets/.env.test b/assets/.env.test index 2d5fdc1..34c4714 100644 --- a/assets/.env.test +++ b/assets/.env.test @@ -1,4 +1,5 @@ -BASE_URL=http://192.168.100.85:6950/api +# BASE_URL=http://192.168.100.85:6950/api +BASE_URL=http://localhost:6950/api CLIENTID=77433712483-ng7pntvcpf6tnjccriuqm8dbna8vvp3b.apps.googleusercontent.com SIMULATE_PAYMENT_SUCCESS=true GATEWAY_SCRIPT_URL=https://test-gateway.mastercard.com/static/checkout/checkout.min.js diff --git a/lib/screens/home/home_controller.dart b/lib/screens/home/home_controller.dart index 96d3159..f2c3908 100644 --- a/lib/screens/home/home_controller.dart +++ b/lib/screens/home/home_controller.dart @@ -62,11 +62,11 @@ abstract class BillProvider with _$BillProvider { required String description, required bool requiresAccount, required bool requiresAmount, - required bool requiresAmountFromMerchant, + required bool? requiresAmountFromMerchant, required bool requiresPhone, - required bool requiresReversal, + required bool? requiresReversal, required String? additionalDataString, - required String processorType, + required String? processorType, required String uid, required String image, required String label, @@ -83,8 +83,16 @@ class HomeController extends ChangeNotifier { final Http http = Http(); BuildContext context; + bool _disposed = false; + HomeController(this.context); + @override + void dispose() { + _disposed = true; + super.dispose(); + } + void _showErrorSnackBar(String? message) { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar( @@ -99,7 +107,7 @@ class HomeController extends ChangeNotifier { Future getAccounts() async { model.accounts = getFakeAccounts(); - notifyListeners(); + if (!_disposed) notifyListeners(); } Future getProviders() async { @@ -108,7 +116,7 @@ class HomeController extends ChangeNotifier { model.transactions = getFakeTransactions(); model.isLoading = true; - notifyListeners(); + if (!_disposed) notifyListeners(); List response = await http.get('/public/providers'); model.providers = response.map((e) => BillProvider.fromJson(e)).toList(); @@ -117,8 +125,9 @@ class HomeController extends ChangeNotifier { if (model.providers.isNotEmpty) { updateSelectedProvider(model.providers[0]); } - } catch (e) { + } catch (e, s) { logger.e(e); + logger.e(s); _showErrorSnackBar( "Problem fetching providers, are you connected to the internet?", ); @@ -128,7 +137,7 @@ class HomeController extends ChangeNotifier { } model.isLoading = false; - notifyListeners(); + if (!_disposed) notifyListeners(); } void updateSelectedProvider(BillProvider provider) { @@ -136,13 +145,13 @@ class HomeController extends ChangeNotifier { // getProducts(provider.uid); - notifyListeners(); + if (!_disposed) notifyListeners(); } Future getTransactions(String userId) async { model.isLoading = true; // model.transactions = getFakeTransactions(); - notifyListeners(); + if (!_disposed) notifyListeners(); try { Map response = await http.get( @@ -163,7 +172,7 @@ class HomeController extends ChangeNotifier { model.transactions = []; } finally { model.isLoading = false; - notifyListeners(); + if (!_disposed) notifyListeners(); } } @@ -171,7 +180,7 @@ class HomeController extends ChangeNotifier { // activate skeletonizer model.categories = getFakeCategoryData(); model.isLoading = true; - notifyListeners(); + if (!_disposed) notifyListeners(); // Simulate fetching categories try { @@ -190,14 +199,14 @@ class HomeController extends ChangeNotifier { model.categories = []; } finally { model.isLoading = false; - notifyListeners(); + if (!_disposed) notifyListeners(); } } Future updateSelectedCategory(Category? category) async { if (category == null) { model.filterableProviders = model.providers; - notifyListeners(); + if (!_disposed) notifyListeners(); return; } @@ -207,7 +216,7 @@ class HomeController extends ChangeNotifier { .where((element) => element.category == category.label) .toList(); - notifyListeners(); + if (!_disposed) notifyListeners(); } List> getFakeTransactions() { diff --git a/lib/screens/home/home_controller.freezed.dart b/lib/screens/home/home_controller.freezed.dart index aaa4658..93ee640 100644 --- a/lib/screens/home/home_controller.freezed.dart +++ b/lib/screens/home/home_controller.freezed.dart @@ -287,7 +287,7 @@ as String, /// @nodoc mixin _$BillProvider { - String get clientId; String get name; String get description; bool get requiresAccount; bool get requiresAmount; bool get requiresAmountFromMerchant; bool get requiresPhone; bool get requiresReversal; String? get additionalDataString; String get processorType; String get uid; String get image; String get label; String get category; String? get accountFieldName; + String get clientId; String get name; String get description; bool get requiresAccount; bool get requiresAmount; bool? get requiresAmountFromMerchant; bool get requiresPhone; bool? get requiresReversal; String? get additionalDataString; String? get processorType; String get uid; String get image; String get label; String get category; String? get accountFieldName; /// Create a copy of BillProvider /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -320,7 +320,7 @@ abstract mixin class $BillProviderCopyWith<$Res> { factory $BillProviderCopyWith(BillProvider value, $Res Function(BillProvider) _then) = _$BillProviderCopyWithImpl; @useResult $Res call({ - String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool requiresAmountFromMerchant, bool requiresPhone, bool requiresReversal, String? additionalDataString, String processorType, String uid, String image, String label, String category, String? accountFieldName + String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool? requiresAmountFromMerchant, bool requiresPhone, bool? requiresReversal, String? additionalDataString, String? processorType, String uid, String image, String label, String category, String? accountFieldName }); @@ -337,19 +337,19 @@ class _$BillProviderCopyWithImpl<$Res> /// Create a copy of BillProvider /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? clientId = null,Object? name = null,Object? description = null,Object? requiresAccount = null,Object? requiresAmount = null,Object? requiresAmountFromMerchant = null,Object? requiresPhone = null,Object? requiresReversal = null,Object? additionalDataString = freezed,Object? processorType = null,Object? uid = null,Object? image = null,Object? label = null,Object? category = null,Object? accountFieldName = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? clientId = null,Object? name = null,Object? description = null,Object? requiresAccount = null,Object? requiresAmount = null,Object? requiresAmountFromMerchant = freezed,Object? requiresPhone = null,Object? requiresReversal = freezed,Object? additionalDataString = freezed,Object? processorType = freezed,Object? uid = null,Object? image = null,Object? label = null,Object? category = null,Object? accountFieldName = freezed,}) { return _then(_self.copyWith( clientId: null == clientId ? _self.clientId : clientId // ignore: cast_nullable_to_non_nullable as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String,requiresAccount: null == requiresAccount ? _self.requiresAccount : requiresAccount // ignore: cast_nullable_to_non_nullable as bool,requiresAmount: null == requiresAmount ? _self.requiresAmount : requiresAmount // ignore: cast_nullable_to_non_nullable -as bool,requiresAmountFromMerchant: null == requiresAmountFromMerchant ? _self.requiresAmountFromMerchant : requiresAmountFromMerchant // ignore: cast_nullable_to_non_nullable -as bool,requiresPhone: null == requiresPhone ? _self.requiresPhone : requiresPhone // ignore: cast_nullable_to_non_nullable -as bool,requiresReversal: null == requiresReversal ? _self.requiresReversal : requiresReversal // ignore: cast_nullable_to_non_nullable -as bool,additionalDataString: freezed == additionalDataString ? _self.additionalDataString : additionalDataString // ignore: cast_nullable_to_non_nullable -as String?,processorType: null == processorType ? _self.processorType : processorType // ignore: cast_nullable_to_non_nullable -as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as bool,requiresAmountFromMerchant: freezed == requiresAmountFromMerchant ? _self.requiresAmountFromMerchant : requiresAmountFromMerchant // ignore: cast_nullable_to_non_nullable +as bool?,requiresPhone: null == requiresPhone ? _self.requiresPhone : requiresPhone // ignore: cast_nullable_to_non_nullable +as bool,requiresReversal: freezed == requiresReversal ? _self.requiresReversal : requiresReversal // ignore: cast_nullable_to_non_nullable +as bool?,additionalDataString: freezed == additionalDataString ? _self.additionalDataString : additionalDataString // ignore: cast_nullable_to_non_nullable +as String?,processorType: freezed == processorType ? _self.processorType : processorType // ignore: cast_nullable_to_non_nullable +as String?,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable as String,category: null == category ? _self.category : category // ignore: cast_nullable_to_non_nullable @@ -439,7 +439,7 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool requiresAmountFromMerchant, bool requiresPhone, bool requiresReversal, String? additionalDataString, String processorType, String uid, String image, String label, String category, String? accountFieldName)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool? requiresAmountFromMerchant, bool requiresPhone, bool? requiresReversal, String? additionalDataString, String? processorType, String uid, String image, String label, String category, String? accountFieldName)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _BillProvider() when $default != null: return $default(_that.clientId,_that.name,_that.description,_that.requiresAccount,_that.requiresAmount,_that.requiresAmountFromMerchant,_that.requiresPhone,_that.requiresReversal,_that.additionalDataString,_that.processorType,_that.uid,_that.image,_that.label,_that.category,_that.accountFieldName);case _: @@ -460,7 +460,7 @@ return $default(_that.clientId,_that.name,_that.description,_that.requiresAccoun /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool requiresAmountFromMerchant, bool requiresPhone, bool requiresReversal, String? additionalDataString, String processorType, String uid, String image, String label, String category, String? accountFieldName) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool? requiresAmountFromMerchant, bool requiresPhone, bool? requiresReversal, String? additionalDataString, String? processorType, String uid, String image, String label, String category, String? accountFieldName) $default,) {final _that = this; switch (_that) { case _BillProvider(): return $default(_that.clientId,_that.name,_that.description,_that.requiresAccount,_that.requiresAmount,_that.requiresAmountFromMerchant,_that.requiresPhone,_that.requiresReversal,_that.additionalDataString,_that.processorType,_that.uid,_that.image,_that.label,_that.category,_that.accountFieldName);case _: @@ -480,7 +480,7 @@ return $default(_that.clientId,_that.name,_that.description,_that.requiresAccoun /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool requiresAmountFromMerchant, bool requiresPhone, bool requiresReversal, String? additionalDataString, String processorType, String uid, String image, String label, String category, String? accountFieldName)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool? requiresAmountFromMerchant, bool requiresPhone, bool? requiresReversal, String? additionalDataString, String? processorType, String uid, String image, String label, String category, String? accountFieldName)? $default,) {final _that = this; switch (_that) { case _BillProvider() when $default != null: return $default(_that.clientId,_that.name,_that.description,_that.requiresAccount,_that.requiresAmount,_that.requiresAmountFromMerchant,_that.requiresPhone,_that.requiresReversal,_that.additionalDataString,_that.processorType,_that.uid,_that.image,_that.label,_that.category,_that.accountFieldName);case _: @@ -503,11 +503,11 @@ class _BillProvider implements BillProvider { @override final String description; @override final bool requiresAccount; @override final bool requiresAmount; -@override final bool requiresAmountFromMerchant; +@override final bool? requiresAmountFromMerchant; @override final bool requiresPhone; -@override final bool requiresReversal; +@override final bool? requiresReversal; @override final String? additionalDataString; -@override final String processorType; +@override final String? processorType; @override final String uid; @override final String image; @override final String label; @@ -547,7 +547,7 @@ abstract mixin class _$BillProviderCopyWith<$Res> implements $BillProviderCopyWi factory _$BillProviderCopyWith(_BillProvider value, $Res Function(_BillProvider) _then) = __$BillProviderCopyWithImpl; @override @useResult $Res call({ - String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool requiresAmountFromMerchant, bool requiresPhone, bool requiresReversal, String? additionalDataString, String processorType, String uid, String image, String label, String category, String? accountFieldName + String clientId, String name, String description, bool requiresAccount, bool requiresAmount, bool? requiresAmountFromMerchant, bool requiresPhone, bool? requiresReversal, String? additionalDataString, String? processorType, String uid, String image, String label, String category, String? accountFieldName }); @@ -564,19 +564,19 @@ class __$BillProviderCopyWithImpl<$Res> /// Create a copy of BillProvider /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? clientId = null,Object? name = null,Object? description = null,Object? requiresAccount = null,Object? requiresAmount = null,Object? requiresAmountFromMerchant = null,Object? requiresPhone = null,Object? requiresReversal = null,Object? additionalDataString = freezed,Object? processorType = null,Object? uid = null,Object? image = null,Object? label = null,Object? category = null,Object? accountFieldName = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? clientId = null,Object? name = null,Object? description = null,Object? requiresAccount = null,Object? requiresAmount = null,Object? requiresAmountFromMerchant = freezed,Object? requiresPhone = null,Object? requiresReversal = freezed,Object? additionalDataString = freezed,Object? processorType = freezed,Object? uid = null,Object? image = null,Object? label = null,Object? category = null,Object? accountFieldName = freezed,}) { return _then(_BillProvider( clientId: null == clientId ? _self.clientId : clientId // ignore: cast_nullable_to_non_nullable as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String,requiresAccount: null == requiresAccount ? _self.requiresAccount : requiresAccount // ignore: cast_nullable_to_non_nullable as bool,requiresAmount: null == requiresAmount ? _self.requiresAmount : requiresAmount // ignore: cast_nullable_to_non_nullable -as bool,requiresAmountFromMerchant: null == requiresAmountFromMerchant ? _self.requiresAmountFromMerchant : requiresAmountFromMerchant // ignore: cast_nullable_to_non_nullable -as bool,requiresPhone: null == requiresPhone ? _self.requiresPhone : requiresPhone // ignore: cast_nullable_to_non_nullable -as bool,requiresReversal: null == requiresReversal ? _self.requiresReversal : requiresReversal // ignore: cast_nullable_to_non_nullable -as bool,additionalDataString: freezed == additionalDataString ? _self.additionalDataString : additionalDataString // ignore: cast_nullable_to_non_nullable -as String?,processorType: null == processorType ? _self.processorType : processorType // ignore: cast_nullable_to_non_nullable -as String,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable +as bool,requiresAmountFromMerchant: freezed == requiresAmountFromMerchant ? _self.requiresAmountFromMerchant : requiresAmountFromMerchant // ignore: cast_nullable_to_non_nullable +as bool?,requiresPhone: null == requiresPhone ? _self.requiresPhone : requiresPhone // ignore: cast_nullable_to_non_nullable +as bool,requiresReversal: freezed == requiresReversal ? _self.requiresReversal : requiresReversal // ignore: cast_nullable_to_non_nullable +as bool?,additionalDataString: freezed == additionalDataString ? _self.additionalDataString : additionalDataString // ignore: cast_nullable_to_non_nullable +as String?,processorType: freezed == processorType ? _self.processorType : processorType // ignore: cast_nullable_to_non_nullable +as String?,uid: null == uid ? _self.uid : uid // ignore: cast_nullable_to_non_nullable as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable as String,category: null == category ? _self.category : category // ignore: cast_nullable_to_non_nullable diff --git a/lib/screens/home/home_controller.g.dart b/lib/screens/home/home_controller.g.dart index cd8707c..36b1e1f 100644 --- a/lib/screens/home/home_controller.g.dart +++ b/lib/screens/home/home_controller.g.dart @@ -27,11 +27,11 @@ _BillProvider _$BillProviderFromJson(Map json) => description: json['description'] as String, requiresAccount: json['requiresAccount'] as bool, requiresAmount: json['requiresAmount'] as bool, - requiresAmountFromMerchant: json['requiresAmountFromMerchant'] as bool, + requiresAmountFromMerchant: json['requiresAmountFromMerchant'] as bool?, requiresPhone: json['requiresPhone'] as bool, - requiresReversal: json['requiresReversal'] as bool, + requiresReversal: json['requiresReversal'] as bool?, additionalDataString: json['additionalDataString'] as String?, - processorType: json['processorType'] as String, + processorType: json['processorType'] as String?, uid: json['uid'] as String, image: json['image'] as String, label: json['label'] as String, diff --git a/lib/screens/integration/integration_controller.dart b/lib/screens/integration/integration_controller.dart index def9934..1fa0457 100644 --- a/lib/screens/integration/integration_controller.dart +++ b/lib/screens/integration/integration_controller.dart @@ -1,4 +1,3 @@ - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -22,6 +21,8 @@ class IntegrationController extends ChangeNotifier { late GatewayController gatewayController; late SharedPreferences prefs; + bool _disposed = false; + BuildContext context; IntegrationController(this.context) { @@ -45,15 +46,14 @@ class IntegrationController extends ChangeNotifier { }); } - Future doIntegration() async { try { model.isLoading = true; notifyListeners(); dynamic workflowResponse = await http.get( - '/public/transaction/integration/' - '${transactionController.model.confirmationData['id']}' + '/public/transaction/integration/' + '${transactionController.model.confirmationData['id']}', ); logger.i(workflowResponse.toString()); @@ -63,21 +63,28 @@ class IntegrationController extends ChangeNotifier { model.status = response['status']; transactionController.updateReceiptData(response); - await gatewayController.poll(transactionController.model.confirmationData['id']); + await gatewayController.poll( + transactionController.model.confirmationData['id'], + ); } // regardless of poll result we proceed to receipt - WidgetsBinding.instance.addPostFrameCallback((_) { - context.go('/receipt'); - }); - model.isLoading = false; - notifyListeners(); + if (!_disposed) notifyListeners(); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (!_disposed && context.mounted) context.go('/receipt'); + }); } catch (e) { model.isLoading = false; model.errorMessage = e.toString(); - notifyListeners(); + if (!_disposed) notifyListeners(); } } -} \ No newline at end of file + + @override + void dispose() { + _disposed = true; + super.dispose(); + } +} diff --git a/lib/screens/pay/pay_screen.dart b/lib/screens/pay/pay_screen.dart index 04e8497..d9ee141 100644 --- a/lib/screens/pay/pay_screen.dart +++ b/lib/screens/pay/pay_screen.dart @@ -6,6 +6,7 @@ import 'package:provider/provider.dart'; import 'package:qpay/models/responsive_policy.dart'; import 'package:qpay/screens/pay/pay_controller.dart'; import 'package:qpay/screens/transaction_controller.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:skeletonizer/skeletonizer.dart'; class PayScreen extends StatefulWidget { @@ -21,6 +22,7 @@ class _PayScreenState extends State with TickerProviderStateMixin { late Animation _slideAnimation; late PayController controller; late TransactionController transactionController; + late SharedPreferences prefs; final List> _animations = []; final _formKey = GlobalKey(); @@ -73,9 +75,7 @@ class _PayScreenState extends State with TickerProviderStateMixin { transactionController.model.formData.creditName ?? ''; _emailController.text = transactionController.model.formData.creditEmail ?? ''; - _amountController.text = - transactionController.model.formData.amount; - + _amountController.text = transactionController.model.formData.amount; // Initialize phone number and country code // updatePhoneNumber(transactionController.model.formData.creditPhone ?? ''); @@ -92,15 +92,13 @@ class _PayScreenState extends State with TickerProviderStateMixin { ), ); - _slideAnimation = Tween( - begin: const Offset(0, 0.1), - end: Offset.zero, - ).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 0.5, curve: Curves.easeOut), - ), - ); + _slideAnimation = + Tween(begin: const Offset(0, 0.1), end: Offset.zero).animate( + CurvedAnimation( + parent: _controller, + curve: const Interval(0.0, 0.5, curve: Curves.easeOut), + ), + ); List buttonIndices = [0, 1]; for (int i = 0; i < buttonIndices.length; i++) { @@ -115,6 +113,14 @@ class _PayScreenState extends State with TickerProviderStateMixin { } _controller.forward(); + _setupData(); + } + + _setupData() async { + prefs = await SharedPreferences.getInstance(); + if (prefs.containsKey('phone')) { + updatePhoneNumber(prefs.getString('phone')!); + } } Future updatePhoneNumber(String phoneNumber) async { @@ -154,15 +160,14 @@ class _PayScreenState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - leading: - context.canPop() - ? IconButton( - onPressed: () { - context.pop(); - }, - icon: const Icon(Icons.arrow_back), - ) - : SizedBox.shrink(), + leading: context.canPop() + ? IconButton( + onPressed: () { + context.pop(); + }, + icon: const Icon(Icons.arrow_back), + ) + : SizedBox.shrink(), title: const Text( 'Make Payment', style: TextStyle(color: Colors.black87), @@ -182,22 +187,30 @@ class _PayScreenState extends State with TickerProviderStateMixin { key: _formKey, child: Center( child: LayoutBuilder( - builder: (context, constraints) { - return SizedBox( - width: double.parse(constraints.maxWidth > ResponsivePolicy.md ? - ResponsivePolicy.md.toString() : - constraints.maxWidth.toString()), + builder: (context, constraints) { + return SizedBox( + width: double.parse( + constraints.maxWidth > ResponsivePolicy.md + ? ResponsivePolicy.md.toString() + : constraints.maxWidth.toString(), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( decoration: BoxDecoration( - border: Border.all(color: Colors.black87.withAlpha(20)), + border: Border.all( + color: Colors.black87.withAlpha(20), + ), borderRadius: BorderRadius.circular(12), ), - padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), + padding: EdgeInsets.symmetric( + vertical: 10, + horizontal: 20, + ), child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Text( "TRANSACTIONS DETAILS", @@ -208,7 +221,8 @@ class _PayScreenState extends State with TickerProviderStateMixin { ), const SizedBox(height: 10), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Text( "Provider", @@ -218,20 +232,25 @@ class _PayScreenState extends State with TickerProviderStateMixin { ), ), Text( - controller.model.selectedProvider?.name ?? "", + controller + .model + .selectedProvider + ?.name ?? + "", style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 10), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Text( controller - .model - .selectedProvider - ?.accountFieldName ?? + .model + .selectedProvider + ?.accountFieldName ?? "", style: TextStyle( fontSize: 16, @@ -271,7 +290,9 @@ class _PayScreenState extends State with TickerProviderStateMixin { ? Icons.arrow_drop_up : Icons.arrow_drop_down, ), - color: Theme.of(context).colorScheme.primary, + color: Theme.of( + context, + ).colorScheme.primary, ), Text( showAdditionalRecipientDetails @@ -299,7 +320,7 @@ class _PayScreenState extends State with TickerProviderStateMixin { ], ), ); - } + }, ), ), ), @@ -326,21 +347,21 @@ class _PayScreenState extends State with TickerProviderStateMixin { 'Debit Phone Number', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), - if(!kIsWeb) - TextButton( - onPressed: () async { - if (await FlutterContacts.requestPermission()) { - final contact = await FlutterContacts.openExternalPick(); - if (contact != null) { - updatePhoneNumber(contact.phones.first.normalizedNumber); + if (!kIsWeb) + TextButton( + onPressed: () async { + if (await FlutterContacts.requestPermission()) { + final contact = await FlutterContacts.openExternalPick(); + if (contact != null) { + updatePhoneNumber(contact.phones.first.normalizedNumber); + } } - } - }, - child: Text( - "Fetch from contacts", - style: TextStyle(fontSize: 12, color: Colors.red), + }, + child: Text( + "Fetch from contacts", + style: TextStyle(fontSize: 12, color: Colors.red), + ), ), - ), ], ), const SizedBox(height: 5), @@ -361,23 +382,22 @@ class _PayScreenState extends State with TickerProviderStateMixin { isExpanded: true, icon: const Icon(Icons.arrow_drop_down), padding: const EdgeInsets.symmetric(horizontal: 8), - items: - countryCodes.map((country) { - return DropdownMenuItem( - value: country['code'], - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text(country['flag']!), - const SizedBox(width: 4), - Text( - country['code']!, - style: const TextStyle(fontSize: 14), - ), - ], + items: countryCodes.map((country) { + return DropdownMenuItem( + value: country['code'], + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(country['flag']!), + const SizedBox(width: 4), + Text( + country['code']!, + style: const TextStyle(fontSize: 14), ), - ); - }).toList(), + ], + ), + ); + }).toList(), onChanged: (String? newValue) { if (newValue != null) { setState(() { @@ -585,8 +605,10 @@ class _PayScreenState extends State with TickerProviderStateMixin { ...controller.model.products.map( (e) => DropdownMenuItem( value: e.uid, - child: Text('${e.displayName} - ' - '${transactionController.model.formData.debitCurrency}${e.defaultAmount}'), + child: Text( + '${e.displayName} - ' + '${transactionController.model.formData.debitCurrency}${e.defaultAmount}', + ), ), ), ],