Proceed or Swipe to pay disabled on over limit
This commit is contained in:
@@ -45,6 +45,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
|
|||||||
final _limitService = getIt<LimitService>();
|
final _limitService = getIt<LimitService>();
|
||||||
Limit? _limit;
|
Limit? _limit;
|
||||||
bool _isLoadingLimit = true;
|
bool _isLoadingLimit = true;
|
||||||
|
bool _isAmountOverLimit = false;
|
||||||
final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹');
|
final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹');
|
||||||
final _amountController = TextEditingController();
|
final _amountController = TextEditingController();
|
||||||
final _remarksController = TextEditingController();
|
final _remarksController = TextEditingController();
|
||||||
@@ -76,21 +77,28 @@ void initState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add this method to check the amount against the limit
|
// Add this method to check the amount against the limit
|
||||||
void _checkAmountLimit() {
|
void _checkAmountLimit() {
|
||||||
if (_limit == null) return;
|
if (_limit == null) return;
|
||||||
|
|
||||||
final amount = double.tryParse(_amountController.text) ?? 0;
|
final amount = double.tryParse(_amountController.text) ?? 0;
|
||||||
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
||||||
|
final bool isOverLimit = amount > remainingLimit;
|
||||||
|
|
||||||
if (amount > remainingLimit) {
|
if (isOverLimit) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (_isAmountOverLimit != isOverLimit) {
|
||||||
|
setState(() {
|
||||||
|
_isAmountOverLimit = isOverLimit;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@@ -490,15 +498,15 @@ void initState() {
|
|||||||
|
|
||||||
// Proceed Button
|
// Proceed Button
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: _onProceed,
|
onPressed: _isAmountOverLimit ? null : _onProceed,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
),
|
),
|
||||||
child: Text(AppLocalizations.of(context).proceed),
|
child: Text(AppLocalizations.of(context).proceed),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹');
|
|||||||
final remarksController = TextEditingController();
|
final remarksController = TextEditingController();
|
||||||
final _ifscFocusNode = FocusNode();
|
final _ifscFocusNode = FocusNode();
|
||||||
final service = getIt<BeneficiaryService>();
|
final service = getIt<BeneficiaryService>();
|
||||||
|
bool _isAmountOverLimit = false;
|
||||||
|
|
||||||
late String accountType;
|
late String accountType;
|
||||||
bool _isValidating = false;
|
bool _isValidating = false;
|
||||||
@@ -88,21 +89,28 @@ Future<void> _loadLimit() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add this method to check the amount against the limit
|
// Add this method to check the amount against the limit
|
||||||
void _checkAmountLimit() {
|
void _checkAmountLimit() {
|
||||||
if (_limit == null) return;
|
if (_limit == null) return;
|
||||||
|
|
||||||
final amount = double.tryParse(amountController.text) ?? 0;
|
final amount = double.tryParse(amountController.text) ?? 0;
|
||||||
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
||||||
|
final bool isOverLimit = amount > remainingLimit;
|
||||||
|
|
||||||
if (amount > remainingLimit) {
|
if (isOverLimit) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (_isAmountOverLimit != isOverLimit) {
|
||||||
|
setState(() {
|
||||||
|
_isAmountOverLimit = isOverLimit;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _validateIFSC() async {
|
void _validateIFSC() async {
|
||||||
final ifsc = ifscController.text.trim().toUpperCase();
|
final ifsc = ifscController.text.trim().toUpperCase();
|
||||||
@@ -856,24 +864,31 @@ if (!_isLoadingLimit && _limit != null)
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 45),
|
const SizedBox(height: 45),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: SwipeButton.expand(
|
child: SwipeButton.expand(
|
||||||
thumb: Icon(Icons.arrow_forward,
|
thumb: Icon(Icons.arrow_forward,
|
||||||
color: Theme.of(context).dialogBackgroundColor),
|
color: _isAmountOverLimit ? Colors.grey : Theme.of(context).dialogBackgroundColor),
|
||||||
activeThumbColor: Theme.of(context).colorScheme.primary,
|
activeThumbColor: _isAmountOverLimit ? Colors.grey.shade700 :
|
||||||
activeTrackColor:
|
Theme.of(context).colorScheme.primary,
|
||||||
Theme.of(context).colorScheme.secondary.withAlpha(100),
|
activeTrackColor: _isAmountOverLimit
|
||||||
borderRadius: BorderRadius.circular(30),
|
? Colors.grey.shade300
|
||||||
height: 56,
|
: Theme.of(context).colorScheme.secondary.withAlpha(100),
|
||||||
onSwipe: _onProceedToPay,
|
borderRadius: BorderRadius.circular(30),
|
||||||
child: Text(
|
height: 56,
|
||||||
AppLocalizations.of(context).swipeToPay,
|
onSwipe: () {
|
||||||
style: const TextStyle(
|
if (_isAmountOverLimit) {
|
||||||
fontSize: 16, fontWeight: FontWeight.bold),
|
return; // Do nothing if amount is over the limit
|
||||||
),
|
}
|
||||||
),
|
_onProceedToPay();
|
||||||
),
|
},
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).swipeToPay,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹');
|
|||||||
final TextEditingController amountController = TextEditingController();
|
final TextEditingController amountController = TextEditingController();
|
||||||
final TextEditingController remarksController = TextEditingController();
|
final TextEditingController remarksController = TextEditingController();
|
||||||
String? _selectedAccountType;
|
String? _selectedAccountType;
|
||||||
|
bool _isAmountOverLimit = false;
|
||||||
String? _beneficiaryName;
|
String? _beneficiaryName;
|
||||||
bool _isValidating = false;
|
bool _isValidating = false;
|
||||||
bool _isBeneficiaryValidated = false;
|
bool _isBeneficiaryValidated = false;
|
||||||
@@ -43,6 +43,7 @@ final _formatCurrency = NumberFormat.currency(locale: 'en_IN', symbol: '₹');
|
|||||||
_loadLimit();
|
_loadLimit();
|
||||||
accountNumberController.addListener(_resetBeneficiaryValidation);
|
accountNumberController.addListener(_resetBeneficiaryValidation);
|
||||||
confirmAccountNumberController.addListener(_resetBeneficiaryValidation);
|
confirmAccountNumberController.addListener(_resetBeneficiaryValidation);
|
||||||
|
amountController.addListener(_checkAmountLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadLimit() async {
|
Future<void> _loadLimit() async {
|
||||||
@@ -68,8 +69,9 @@ void _checkAmountLimit() {
|
|||||||
|
|
||||||
final amount = double.tryParse(amountController.text) ?? 0;
|
final amount = double.tryParse(amountController.text) ?? 0;
|
||||||
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
final remainingLimit = _limit!.dailyLimit - _limit!.usedLimit;
|
||||||
|
final bool isOverLimit = amount > remainingLimit;
|
||||||
|
|
||||||
if (amount > remainingLimit) {
|
if (isOverLimit) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
content: Text('Amount exceeds remaining daily limit of ${_formatCurrency.format(remainingLimit)}'),
|
||||||
@@ -77,6 +79,13 @@ void _checkAmountLimit() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update state only if it changes to avoid unnecessary rebuilds
|
||||||
|
if (_isAmountOverLimit != isOverLimit) {
|
||||||
|
setState(() {
|
||||||
|
_isAmountOverLimit = isOverLimit;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _resetBeneficiaryValidation() {
|
void _resetBeneficiaryValidation() {
|
||||||
@@ -379,63 +388,69 @@ if (!_isLoadingLimit && _limit != null)
|
|||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 45),
|
const SizedBox(height: 45),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: SwipeButton.expand(
|
child: SwipeButton.expand(
|
||||||
thumb: Icon(Icons.arrow_forward,
|
thumb: Icon(Icons.arrow_forward,
|
||||||
color: Theme.of(context).dialogBackgroundColor),
|
color: _isAmountOverLimit ? Colors.grey : Theme.of(context).dialogBackgroundColor),
|
||||||
activeThumbColor: Theme.of(context).colorScheme.primary,
|
activeThumbColor: _isAmountOverLimit ? Colors.grey.shade700 :
|
||||||
activeTrackColor: Theme.of(
|
Theme.of(context).colorScheme.primary,
|
||||||
context,
|
activeTrackColor: _isAmountOverLimit
|
||||||
).colorScheme.secondary.withAlpha(100),
|
? Colors.grey.shade300
|
||||||
borderRadius: BorderRadius.circular(30),
|
: Theme.of(
|
||||||
height: 56,
|
context,
|
||||||
child: Text(
|
).colorScheme.secondary.withAlpha(100),
|
||||||
AppLocalizations.of(context).swipeToPay,
|
borderRadius: BorderRadius.circular(30),
|
||||||
style: const TextStyle(fontSize: 16),
|
height: 56,
|
||||||
),
|
child: Text(
|
||||||
onSwipe: () {
|
AppLocalizations.of(context).swipeToPay,
|
||||||
if (_formKey.currentState!.validate()) {
|
style: const TextStyle(fontSize: 16),
|
||||||
if (!_isBeneficiaryValidated) {
|
),
|
||||||
setState(() {
|
onSwipe: () {
|
||||||
_validationError = AppLocalizations.of(context)
|
if (_isAmountOverLimit) {
|
||||||
.validateBeneficiaryproceeding;
|
return; // Do nothing if amount is over limit
|
||||||
});
|
}
|
||||||
return;
|
if (_formKey.currentState!.validate()) {
|
||||||
}
|
if (!_isBeneficiaryValidated) {
|
||||||
// Perform payment logic
|
setState(() {
|
||||||
Navigator.push(
|
_validationError = AppLocalizations.of(context)
|
||||||
context,
|
.validateBeneficiaryproceeding;
|
||||||
MaterialPageRoute(
|
});
|
||||||
builder: (context) => TransactionPinScreen(
|
return;
|
||||||
onPinCompleted: (pinScreenContext, tpin) async {
|
}
|
||||||
final transfer = Transfer(
|
// Perform payment logic
|
||||||
fromAccount: widget.debitAccount,
|
Navigator.push(
|
||||||
toAccount: accountNumberController.text,
|
context,
|
||||||
toAccountType: _selectedAccountType!,
|
MaterialPageRoute(
|
||||||
amount: amountController.text,
|
builder: (context) => TransactionPinScreen(
|
||||||
tpin: tpin,
|
onPinCompleted: (pinScreenContext, tpin) async {
|
||||||
remarks: remarksController.text,
|
final transfer = Transfer(
|
||||||
);
|
fromAccount: widget.debitAccount,
|
||||||
|
toAccount: accountNumberController.text,
|
||||||
|
toAccountType: _selectedAccountType!,
|
||||||
|
amount: amountController.text,
|
||||||
|
tpin: tpin,
|
||||||
|
remarks: remarksController.text,
|
||||||
|
);
|
||||||
|
|
||||||
final paymentService = getIt<PaymentService>();
|
final paymentService = getIt<PaymentService>();
|
||||||
final paymentResponseFuture = paymentService
|
final paymentResponseFuture = paymentService
|
||||||
.processQuickPayWithinBank(transfer);
|
.processQuickPayWithinBank(transfer);
|
||||||
|
|
||||||
Navigator.of(pinScreenContext).pushReplacement(
|
Navigator.of(pinScreenContext).pushReplacement(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => PaymentAnimationScreen(
|
builder: (_) => PaymentAnimationScreen(
|
||||||
paymentResponse: paymentResponseFuture),
|
paymentResponse: paymentResponseFuture),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user