From d86ff2c42731e3a029e1112ac512dd7bd6557a90 Mon Sep 17 00:00:00 2001 From: Nilanjan Chakrabarti Date: Fri, 31 Oct 2025 16:31:04 +0530 Subject: [PATCH] Snackbar added in amount screens --- .../screens/fund_transfer_amount_screen.dart | 56 +++++++++++++++++ .../quick_pay_outside_bank_screen.dart | 63 ++++++++++++++++++- .../screens/quick_pay_within_bank_screen.dart | 56 ++++++++++++++++- 3 files changed, 172 insertions(+), 3 deletions(-) diff --git a/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart b/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart index 98898f9..6ddd1a6 100644 --- a/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart +++ b/lib/features/fund_transfer/screens/fund_transfer_amount_screen.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:kmobile/api/services/limit_service.dart'; import 'package:kmobile/api/services/neft_service.dart'; import 'package:kmobile/api/services/rtgs_service.dart'; import 'package:kmobile/api/services/imps_service.dart'; @@ -40,13 +42,59 @@ class FundTransferAmountScreen extends StatefulWidget { } class _FundTransferAmountScreenState extends State { + final _limitService = getIt(); +Limit? _limit; +bool _isLoadingLimit = true; +final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹'); final _amountController = TextEditingController(); final _remarksController = TextEditingController(); final _formKey = GlobalKey(); TransactionMode _selectedMode = TransactionMode.neft; +@override +void initState() { + super.initState(); + _loadLimit(); // Call the new method + _amountController.addListener(_checkAmountLimit); +} + Future _loadLimit() async { + setState(() { + _isLoadingLimit = true; + }); + try { + final limitData = await _limitService.getLimit(); + setState(() { + _limit = limitData; + _isLoadingLimit = false; + }); + } catch (e) { + // Handle error if needed + setState(() { + _isLoadingLimit = false; + }); + } + } + + // Add this method to check the amount against the limit + void _checkAmountLimit() { + if (_limit == null) return; + + final amount = double.tryParse(_amountController.text) ?? 0; + final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit; + + if (amount > remainingLimit) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'), + backgroundColor: Colors.red, + ), + ); + } + } + @override void dispose() { + _amountController.removeListener(_checkAmountLimit); _amountController.dispose(); _remarksController.dispose(); super.dispose(); @@ -430,6 +478,14 @@ class _FundTransferAmountScreenState extends State { return null; }, ), + const SizedBox(height: 8), + if (_isLoadingLimit) + const Text('Fetching daily limit...'), + if (!_isLoadingLimit && _limit != null) + Text( + 'Remaining Daily Limit: ${_formatCurrency.format(_limit!.dailyLimit - _limit!.usedLimit)}', + style: Theme.of(context).textTheme.bodySmall, + ), const Spacer(), // Proceed Button diff --git a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart index ea1b36a..808365e 100644 --- a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart @@ -2,7 +2,9 @@ import 'dart:async'; import 'dart:developer'; import 'package:dio/dio.dart'; import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; import 'package:kmobile/api/services/imps_service.dart'; +import 'package:kmobile/api/services/limit_service.dart'; import 'package:kmobile/api/services/neft_service.dart'; import 'package:kmobile/api/services/rtgs_service.dart'; import 'package:kmobile/data/models/imps_transaction.dart'; @@ -28,7 +30,10 @@ class QuickPayOutsideBankScreen extends StatefulWidget { class _QuickPayOutsideBankScreen extends State { final _formKey = GlobalKey(); - + final _limitService = getIt(); +Limit? _limit; +bool _isLoadingLimit = true; +final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹'); // Controllers final accountNumberController = TextEditingController(); final confirmAccountNumberController = TextEditingController(); @@ -50,6 +55,7 @@ class _QuickPayOutsideBankScreen extends State { @override void initState() { super.initState(); + _loadLimit(); _ifscFocusNode.addListener(() { if (!_ifscFocusNode.hasFocus && ifscController.text.trim().length == 11) { _validateIFSC(); @@ -60,8 +66,44 @@ class _QuickPayOutsideBankScreen extends State { accountType = 'Savings'; }); }); + amountController.addListener(_checkAmountLimit); } +Future _loadLimit() async { + setState(() { + _isLoadingLimit = true; + }); + try { + final limitData = await _limitService.getLimit(); + setState(() { + _limit = limitData; + _isLoadingLimit = false; + }); + } catch (e) { + // Handle error if needed + setState(() { + _isLoadingLimit = false; + }); + } +} + +// Add this method to check the amount against the limit +void _checkAmountLimit() { + if (_limit == null) return; + + final amount = double.tryParse(amountController.text) ?? 0; + final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit; + + if (amount > remainingLimit) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'), + backgroundColor: Colors.red, + ), + ); + } +} + void _validateIFSC() async { final ifsc = ifscController.text.trim().toUpperCase(); if (ifsc.isEmpty) return; @@ -718,6 +760,9 @@ class _QuickPayOutsideBankScreen extends State { ), ), const SizedBox(height: 25), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Row( children: [ Expanded( @@ -783,6 +828,22 @@ class _QuickPayOutsideBankScreen extends State { ), ], ), + ], + ), + const SizedBox(height: 8), +if (_isLoadingLimit) + const Padding( + padding: EdgeInsets.only(left: 8.0), + child: Text('Fetching daily limit...'), + ), +if (!_isLoadingLimit && _limit != null) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text( + 'Remaining Daily Limit: ${_formatCurrency.format(_limit!.dailyLimit - _limit!.usedLimit)}', + style: Theme.of(context).textTheme.bodySmall, + ), + ), const SizedBox(height: 30), Row( children: [ diff --git a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart index 1f1c3d9..3c3b14c 100644 --- a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_swipe_button/flutter_swipe_button.dart'; +import 'package:intl/intl.dart'; import 'package:kmobile/api/services/beneficiary_service.dart'; +import 'package:kmobile/api/services/limit_service.dart'; import 'package:kmobile/api/services/payment_service.dart'; import 'package:kmobile/data/models/transfer.dart'; import 'package:kmobile/di/injection.dart'; @@ -19,7 +21,10 @@ class QuickPayWithinBankScreen extends StatefulWidget { class _QuickPayWithinBankScreen extends State { final _formKey = GlobalKey(); - + final _limitService = getIt(); +Limit? _limit; +bool _isLoadingLimit = true; +final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹'); final TextEditingController accountNumberController = TextEditingController(); final TextEditingController confirmAccountNumberController = TextEditingController(); @@ -35,10 +40,45 @@ class _QuickPayWithinBankScreen extends State { @override void initState() { super.initState(); + _loadLimit(); accountNumberController.addListener(_resetBeneficiaryValidation); confirmAccountNumberController.addListener(_resetBeneficiaryValidation); } +Future _loadLimit() async { + setState(() { + _isLoadingLimit = true; + }); + try { + final limitData = await _limitService.getLimit(); + setState(() { + _limit = limitData; + _isLoadingLimit = false; + }); + } catch (e) { + // Handle error if needed + setState(() { + _isLoadingLimit = false; + }); + } +} + +void _checkAmountLimit() { + if (_limit == null) return; + + final amount = double.tryParse(amountController.text) ?? 0; + final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit; + + if (amount > remainingLimit) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'), + backgroundColor: Colors.red, + ), + ); + } +} + void _resetBeneficiaryValidation() { if (_isBeneficiaryValidated || _beneficiaryName != null || @@ -53,6 +93,7 @@ class _QuickPayWithinBankScreen extends State { @override void dispose() { + amountController.removeListener(_checkAmountLimit); accountNumberController.removeListener(_resetBeneficiaryValidation); confirmAccountNumberController.removeListener(_resetBeneficiaryValidation); accountNumberController.dispose(); @@ -102,7 +143,8 @@ class _QuickPayWithinBankScreen extends State { padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, - child: Column( + child: SingleChildScrollView( + child: Column( children: [ const SizedBox(height: 10), TextFormField( @@ -297,6 +339,7 @@ class _QuickPayWithinBankScreen extends State { ), ), const SizedBox(height: 25), + TextFormField( decoration: InputDecoration( labelText: AppLocalizations.of(context).amount, @@ -327,6 +370,14 @@ class _QuickPayWithinBankScreen extends State { return null; }, ), + const SizedBox(height: 8), +if (_isLoadingLimit) + const Text('Fetching daily limit...'), +if (!_isLoadingLimit && _limit != null) + Text( + 'Remaining Daily Limit: ${_formatCurrency.format(_limit!.dailyLimit - _limit!.usedLimit)}', + style: Theme.of(context).textTheme.bodySmall, + ), const SizedBox(height: 45), Align( alignment: Alignment.center, @@ -387,6 +438,7 @@ class _QuickPayWithinBankScreen extends State { ), ], ), + ), ), ), );