From dc5169029236f263510bfc18d76214cd4464aac5 Mon Sep 17 00:00:00 2001 From: asif Date: Mon, 2 Feb 2026 18:18:04 +0530 Subject: [PATCH] Revoke Stop base Created --- lib/di/injection.dart | 4 +- .../screens/cheque_management_screen.dart | 2 +- .../screens/revoke _stop_multiple_screen.dart | 337 ++++++++++ .../cheque/screens/revoke_stop_screen.dart | 326 ++++----- .../screens/revoke_stop_single_screen.dart | 619 +++++++++--------- 5 files changed, 799 insertions(+), 489 deletions(-) diff --git a/lib/di/injection.dart b/lib/di/injection.dart index 3913224..43826f1 100644 --- a/lib/di/injection.dart +++ b/lib/di/injection.dart @@ -76,9 +76,9 @@ Dio _createDioClient() { final dio = Dio( BaseOptions( baseUrl: - // 'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com', //test + 'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com', //test //'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod - 'https://kccbmbnk.net', //prod small + //'https://kccbmbnk.net', //prod small connectTimeout: const Duration(seconds: 60), receiveTimeout: const Duration(seconds: 60), headers: { diff --git a/lib/features/cheque/screens/cheque_management_screen.dart b/lib/features/cheque/screens/cheque_management_screen.dart index 06cf465..e34581d 100644 --- a/lib/features/cheque/screens/cheque_management_screen.dart +++ b/lib/features/cheque/screens/cheque_management_screen.dart @@ -85,7 +85,7 @@ class _ChequeManagementScreen extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => RevokeStopSingleChequeScreen( + builder: (context) => RevokeStopChequeScreen( users: users, selectedIndex: selectedAccountIndex, ), diff --git a/lib/features/cheque/screens/revoke _stop_multiple_screen.dart b/lib/features/cheque/screens/revoke _stop_multiple_screen.dart index e69de29..aa4babc 100644 --- a/lib/features/cheque/screens/revoke _stop_multiple_screen.dart +++ b/lib/features/cheque/screens/revoke _stop_multiple_screen.dart @@ -0,0 +1,337 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:kmobile/api/services/cheque_service.dart'; +import 'package:kmobile/data/models/user.dart'; +import 'package:kmobile/di/injection.dart'; +import 'package:kmobile/features/fund_transfer/screens/transaction_pin_screen.dart'; +import 'package:kmobile/l10n/app_localizations.dart'; + +class RevokeStopMultipleChequesScreen extends StatefulWidget { + final User selectedAccount; + final String date; + final String instrType; + final String fromCheque; + final String toCheque; + + const RevokeStopMultipleChequesScreen( + {super.key, + required this.selectedAccount, + required this.date, + required this.instrType, + required this.fromCheque, + required this.toCheque}); + + @override + State createState() => + _RevokeStopMultipleChequesScreenState(); +} + +class _RevokeStopMultipleChequesScreenState extends State { + final _formKey = GlobalKey(); + final _stopFromChequeNoController = TextEditingController(); + final _stopToChequeNoController = TextEditingController(); + final _stopIssueDateController = TextEditingController(); + final _stopExpiryDateController = TextEditingController(); + final _stopAmountController = TextEditingController(); + final _chequeService = getIt(); + + String? _selectedComment; + final _otherCommentController = TextEditingController(); + bool _showOtherCommentField = false; + final List _commentOptions = [ + 'Cheque Found', + 'Cheque Fixed', + 'Other' + ]; + + Future _selectDate(TextEditingController controller) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), + lastDate: DateTime(2101), + ); + if (picked != null) { + setState(() { + controller.text = + '${picked.day.toString().padLeft(2, '0')}/${picked.month.toString().padLeft(2, '0')}/${picked.year}'; + }); + } + } + + Future _showResponseDialog(String title, String message) async { + return showDialog( + context: context, + barrierDismissible: false, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(AppLocalizations.of(context).stopMultipleChequesTitle), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: ListView( + children: [ + Card( + elevation: 0, + margin: const EdgeInsets.symmetric(vertical: 8.0), + child: ListTile( + leading: Image.asset( + 'assets/images/logo.png', + width: 40, + height: 40, + ), + title: Text(widget.selectedAccount.accountNo!), + subtitle: + Text(AppLocalizations.of(context).accountNumberTitle), + ), + ), + const SizedBox(height: 24), + TextFormField( + controller: _stopFromChequeNoController, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).fromChequeNumberHint, + border: const OutlineInputBorder(), + errorMaxLines: 2, + ), + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return AppLocalizations.of(context) + .pleaseEnterChequeNumberError; + } + final chequeNumber = int.tryParse(value); + final fromCheque = int.tryParse(widget.fromCheque); + final toCheque = int.tryParse(widget.toCheque); + if (chequeNumber == null || + fromCheque == null || + toCheque == null) { + return AppLocalizations.of(context) + .invalidChequeNumberFormatError; + } + // if (chequeNumber < fromCheque || chequeNumber > toCheque) { + // return AppLocalizations.of(context).chequeNumberRangeError( + // widget.fromCheque, widget.toCheque); + // } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopToChequeNoController, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).toChequeNumberHint, + border: const OutlineInputBorder(), + errorMaxLines: 2, + ), + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return AppLocalizations.of(context) + .pleaseEnterChequeNumberError; + } + final chequeNumber = int.tryParse(value); + final fromCheque = int.tryParse(widget.fromCheque); + final toCheque = int.tryParse(widget.toCheque); + if (chequeNumber == null || + fromCheque == null || + toCheque == null) { + return AppLocalizations.of(context) + .invalidChequeNumberFormatError; + } + // if (chequeNumber < fromCheque || chequeNumber > toCheque) { + // return AppLocalizations.of(context).chequeNumberRangeError( + // widget.fromCheque, widget.toCheque); + // } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + initialValue: widget.instrType, + readOnly: true, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).instrumentTypeLabel, + border: const OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopIssueDateController, + readOnly: true, + onTap: () => _selectDate(_stopIssueDateController), + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopIssueDateHint, + border: const OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.calendar_today), + onPressed: () => _selectDate(_stopIssueDateController), + ), + ), + keyboardType: TextInputType.datetime, + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopExpiryDateController, + readOnly: true, + onTap: () => _selectDate(_stopExpiryDateController), + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopExpiryDateHint, + border: const OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.calendar_today), + onPressed: () => _selectDate(_stopExpiryDateController), + ), + ), + keyboardType: TextInputType.datetime, + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopAmountController, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopAmountHint, + border: const OutlineInputBorder(), + ), + keyboardType: TextInputType.number, + ), + const SizedBox(height: 16), + DropdownButtonFormField( + value: _selectedComment, + items: _commentOptions.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + _selectedComment = newValue; + _showOtherCommentField = newValue == 'Other'; + }); + }, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopCommentHint, + border: const OutlineInputBorder(), + ), + ), + if (_showOtherCommentField) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: TextFormField( + controller: _otherCommentController, + decoration: const InputDecoration( + labelText: "Other Reasons :", + border: OutlineInputBorder(), + ), + validator: (value) { + return null; + }, + ), + ), + const SizedBox(height: 32), + ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TransactionPinScreen( + onPinCompleted: (ctx, pin) async { + Navigator.pop(context); + try { + final response = await _chequeService.revokeStop( + accountno: widget.selectedAccount.accountNo!, + removeFromChequeNo: + _stopFromChequeNoController.text, + instrType: widget.instrType, + removeToChequeNo: + _stopToChequeNoController.text, + removeIssueDate: _stopIssueDateController.text, + removeExpiryDate: _stopExpiryDateController.text, + removeAmount: _stopAmountController.text, + removeComment: _selectedComment == 'Other' + ? _otherCommentController.text + : _selectedComment ?? '', + tpin: pin, + ); + if (!mounted) return; + final decodedResponse = jsonDecode(response); + String responseString = response.toString(); // used as the case only for incorrect TPIN + final status = decodedResponse['status']; + final message = decodedResponse['message']; + final code = decodedResponse['code']; + if (status == 'SUCCESS') { + _showResponseDialog('Success', message); + } if (status == 'ERROR') { + String errMessage = "error"; + if(code == '0429') { + errMessage = 'The selected Cheque is already stopped'; + } else if(code == '0748') { + errMessage = 'The selected Cheque is already presented'; + } + _showResponseDialog('Error', errMessage); + } + if(responseString.contains('INCORRECT_TPIN')){ + _showResponseDialog('Invalid TPIN', + 'The TPIN you entered is incorrect. Please try again.'); + } + } on Exception catch (e) { + try { + final errorBodyString = + e.toString().split('Exception: ')[1]; + final errorBody = jsonDecode(errorBodyString); + if (errorBody.containsKey('error') && + errorBody['error'] == 'INCORRECT_TPIN') { + _showResponseDialog('Invalid TPIN', + 'The TPIN you entered is incorrect. Please try again.'); + } else { + _showResponseDialog( + 'Error', 'Internal Server Error'); + } + } catch (_) { + _showResponseDialog( + 'Error', 'Internal Server Error'); + } + } + }, + ), + ), + ); + } + }, + child: Text(AppLocalizations.of(context).stopChequeButton), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/features/cheque/screens/revoke_stop_screen.dart b/lib/features/cheque/screens/revoke_stop_screen.dart index 62f9052..f75eb86 100644 --- a/lib/features/cheque/screens/revoke_stop_screen.dart +++ b/lib/features/cheque/screens/revoke_stop_screen.dart @@ -2,15 +2,15 @@ import 'package:kmobile/data/models/user.dart'; import 'package:kmobile/di/injection.dart'; import 'package:flutter/material.dart'; import 'package:kmobile/api/services/cheque_service.dart'; -import 'package:kmobile/features/cheque/screens/stop_multiple_cheques_screen.dart'; -import 'package:kmobile/features/cheque/screens/stop_single_cheque_screen.dart'; +import 'package:kmobile/features/cheque/screens/revoke%20_stop_multiple_screen.dart'; +import 'package:kmobile/features/cheque/screens/revoke_stop_single_screen.dart'; import 'package:kmobile/l10n/app_localizations.dart'; -class RevokeStopSingleChequeScreen extends StatefulWidget { +class RevokeStopChequeScreen extends StatefulWidget { final List users; final int selectedIndex; - const RevokeStopSingleChequeScreen( + const RevokeStopChequeScreen( { super.key, required this.users, @@ -18,14 +18,14 @@ class RevokeStopSingleChequeScreen extends StatefulWidget { }); @override - State createState() => _RevokeStopSingleChequeScreenState(); + State createState() => _RevokeStopChequeScreenState(); } -class _RevokeStopSingleChequeScreenState extends State { - User? _selectedAccount; +class _RevokeStopChequeScreenState extends State { + User? _selectedAccount; var service = getIt(); bool _isLoading = true; - Cheque? _stCheque; + List _stCheques = []; List _filteredUsers = []; @override @@ -58,7 +58,7 @@ class _RevokeStopSingleChequeScreenState extends State cheque.type == 'ST').toList(); setState(() { - _stCheque = stCheques.isNotEmpty ? stCheques.first : null; + _stCheques = stCheques; _isLoading = false; }); } catch (e) { setState(() { _isLoading = false; - _stCheque = null; + _stCheques = []; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -122,170 +122,173 @@ class _RevokeStopSingleChequeScreenState extends State( - value: _selectedAccount, - onChanged: (User? newUser) { - if (newUser != null) { - setState(() { - _selectedAccount = newUser; - _loadCheques(); - }); - } - }, - items: _filteredUsers.map((user) { - return DropdownMenuItem( - value: user, - child: Text(user.accountNo.toString()), - ); - }).toList(), - ), - ) - else - Text(AppLocalizations.of(context).noAccountsFound), - ], - ), + child: Column(children: [ + Card( + elevation: 4, + margin: const EdgeInsets.symmetric(vertical: 8.0), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + AppLocalizations.of(context).accountNumber, + style: const TextStyle( + fontWeight: FontWeight.bold, fontSize: 18), + ), + const SizedBox(width: 16), + if (_selectedAccount != null) + Expanded( + child: DropdownButton( + value: _selectedAccount, + onChanged: (User? newUser) { + if (newUser != null) { + setState(() { + _selectedAccount = newUser; + _loadCheques(); + }); + } + }, + items: _filteredUsers.map((user) { + return DropdownMenuItem( + value: user, + child: Text(user.accountNo.toString()), + ); + }).toList(), + ), + ) + else + Text(AppLocalizations.of(context).noAccountsFound), + ], ), ), - const SizedBox(height: 20), - Row( - children: [ - Expanded( - child: Card( - color: Theme.of(context).colorScheme.primaryContainer, - elevation: 4, - child: InkWell( - onTap: () { - if (_selectedAccount != null && _stCheque != null) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StopSingleChequeScreen( - selectedAccount: _selectedAccount!, - date: _stCheque!.Date!, - instrType: _stCheque!.InstrType!, - fromCheque: _stCheque!.fromCheque!, - toCheque: _stCheque!.toCheque!, - ), - ), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context) - .noChequebookToStop), - ), - ); - } - }, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Center( - child: Text( - AppLocalizations.of(context) - .stopSingleChequeTitle, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .colorScheme - .onPrimaryContainer, + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: Card( + color: Theme.of(context).colorScheme.primaryContainer, + elevation: 4, + child: InkWell( + onTap: () { + if (_selectedAccount != null && + _stCheques.isNotEmpty) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + RevokeStopSingleChequeScreen( + selectedAccount: _selectedAccount!, + date: _stCheques.first.Date!, + instrType: _stCheques.first.InstrType!, + fromCheque: _stCheques.first.fromCheque!, + toCheque: _stCheques.first.toCheque!, ), ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("No stopped cheques present"), + ), + ); + } + }, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text( + "Revoke Single Stop", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, + ), ), ), ), ), ), - const SizedBox(width: 10), - Expanded( - child: Card( - color: Theme.of(context).colorScheme.primaryContainer, - elevation: 4, - child: InkWell( - onTap: () { - if (_selectedAccount != null) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - StopMultipleChequesScreen( - selectedAccount: _selectedAccount!, - date: _stCheque!.Date!, - instrType: _stCheque!.InstrType!, - fromCheque: _stCheque!.fromCheque!, - toCheque: _stCheque!.toCheque!, - ), - ), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context) - .pleaseSelectAccountFirst), - ), - ); - } - }, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Center( - child: Text( - AppLocalizations.of(context) - .stopMultipleChequesButton, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + ), + const SizedBox(width: 10), + Expanded( + child: Card( + color: Theme.of(context).colorScheme.primaryContainer, + elevation: 4, + child: InkWell( + onTap: () { + if (_selectedAccount != null && + _stCheques.isNotEmpty) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + RevokeStopMultipleChequesScreen( + selectedAccount: _selectedAccount!, + date: _stCheques.first.Date!, + instrType: _stCheques.first.InstrType!, + fromCheque: _stCheques.first.fromCheque!, + toCheque: _stCheques.first.toCheque!, ), ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context) + .pleaseSelectAccountFirst), + ), + ); + } + }, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text( + "Revoke Multiple Stops", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), ), ), ), ), ), - ], - ), - const SizedBox(height: 20), - Expanded( - child: _isLoading - ? const Center(child: CircularProgressIndicator()) - : _stCheque == null - ? Center( - child: Text(AppLocalizations.of(context) - .noChequeIssuedStatus)) - : _buildCiTile(context, _stCheque!), - ), - ], - ), + ), + ], + ), + const SizedBox(height: 20), + Expanded( + child: _isLoading + ? const Center(child: CircularProgressIndicator()) + : _stCheques.isEmpty + ? Center( + child: Text(AppLocalizations.of(context) + .noChequeIssuedStatus)) + : ListView.builder( + itemCount: _stCheques.length, + itemBuilder: (context, index) { + return _buildSTTile(context, _stCheques[index]); + }, + ), + ), + ]), ), IgnorePointer( child: Center( @@ -306,7 +309,7 @@ class _RevokeStopSingleChequeScreenState extends State createState() => _RevokeStopSingleChequeScreenState(); -// } + @override + State createState() => _RevokeStopSingleChequeScreenState(); +} -// class _RevokeStopSingleChequeScreenState extends State { -// final _formKey = GlobalKey(); -// final _stopFromChequeNoController = TextEditingController(); -// final _stopIssueDateController = TextEditingController(); -// final _stopExpiryDateController = TextEditingController(); -// final _stopAmountController = TextEditingController(); -// final _chequeService = getIt(); +class _RevokeStopSingleChequeScreenState extends State { + final _formKey = GlobalKey(); + final _stopFromChequeNoController = TextEditingController(); + final _stopIssueDateController = TextEditingController(); + final _stopExpiryDateController = TextEditingController(); + final _stopAmountController = TextEditingController(); + final _chequeService = getIt(); -// String? _selectedComment; -// final _otherCommentController = TextEditingController(); -// bool _showOtherCommentField = false; -// final List _commentOptions = [ -// 'Cheque Lost', -// 'Cheque Stolen', -// 'Cheque Missing', -// 'Cheque Damaged', -// 'Other' -// ]; + String? _selectedComment; + final _otherCommentController = TextEditingController(); + bool _showOtherCommentField = false; + final List _commentOptions = [ + 'Cheque Found', + 'Cheque Fixed', + 'Other' + ]; -// String _formatDate(String dateString) { -// if (dateString.length != 8) { -// return dateString; // Return as is if not in expected ddmmyyyy format -// } -// try { -// final day = dateString.substring(0, 2); -// final month = dateString.substring(2, 4); -// final year = dateString.substring(4, 8); -// return '$day/$month/$year'; -// } catch (e) { -// return dateString; // Return original string on error -// } -// } + Future _selectDate(TextEditingController controller) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), + lastDate: DateTime(2101), + ); + if (picked != null) { + setState(() { + controller.text = + '${picked.day.toString().padLeft(2, '0')}/${picked.month.toString().padLeft(2, '0')}/${picked.year}'; + }); + } + } -// Future _selectDate(TextEditingController controller) async { -// final DateTime? picked = await showDatePicker( -// context: context, -// initialDate: DateTime.now(), -// firstDate: DateTime.now(), -// lastDate: DateTime(2101), -// ); -// if (picked != null) { -// setState(() { -// controller.text = -// '${picked.day.toString().padLeft(2, '0')}/${picked.month.toString().padLeft(2, '0')}/${picked.year}'; -// }); -// } -// } + Future _showResponseDialog(String title, String message) async { + return showDialog( + context: context, + barrierDismissible: false, // user must tap button! + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(message), + ], + ), + ), + actions: [ + TextButton( + child: Text(AppLocalizations.of(context).closeButton), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } -// Future _showResponseDialog(String title, String message) async { -// return showDialog( -// context: context, -// barrierDismissible: false, // user must tap button! -// builder: (BuildContext context) { -// return AlertDialog( -// title: Text(title), -// content: SingleChildScrollView( -// child: ListBody( -// children: [ -// Text(message), -// ], -// ), -// ), -// actions: [ -// TextButton( -// child: Text(AppLocalizations.of(context).closeButton), -// onPressed: () { -// Navigator.of(context).pop(); -// }, -// ), -// ], -// ); -// }, -// ); -// } - -// @override -// Widget build(BuildContext context) { -// return Scaffold( -// appBar: AppBar( -// title: const Text("Revoke Stop")), -// ); -// body: Padding( -// padding: const EdgeInsets.all(16.0), -// child: Form( -// key: _formKey, -// child: ListView( -// children: [ -// Card( -// elevation: 0, -// margin: const EdgeInsets.symmetric(vertical: 8.0), -// child: ListTile( -// leading: Image.asset( -// 'assets/images/logo.png', -// width: 40, -// height: 40, -// ), -// title: Text(widget.selectedAccount.accountNo!), -// subtitle: -// Text(AppLocalizations.of(context).accountNumberLabel), -// ), -// ), -// const SizedBox(height: 24), -// TextFormField( -// controller: _stopFromChequeNoController, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).chequeNumberLabel, -// border: OutlineInputBorder(), -// errorMaxLines: 2, -// ), -// keyboardType: TextInputType.number, -// validator: (value) { -// if (value == null || value.isEmpty) { -// return AppLocalizations.of(context) -// .pleaseEnterChequeNumberError; -// } -// final chequeNumber = int.tryParse(value); -// final fromCheque = int.tryParse(widget.fromCheque); -// final toCheque = int.tryParse(widget.toCheque); -// if (chequeNumber == null || -// fromCheque == null || -// toCheque == null) { -// return AppLocalizations.of(context) -// .invalidChequeNumberFormatError; -// } -// if (chequeNumber < fromCheque || chequeNumber > toCheque) { -// return AppLocalizations.of(context).chequeNumberRangeError( -// widget.fromCheque, widget.toCheque); -// } -// return null; -// }, -// ), -// const SizedBox(height: 16), -// TextFormField( -// initialValue: widget.instrType, -// readOnly: true, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).instrumentTypeLabel, -// border: const OutlineInputBorder(), -// ), -// ), -// const SizedBox(height: 16), -// TextFormField( -// controller: _stopIssueDateController, -// readOnly: true, -// onTap: () => _selectDate(_stopIssueDateController), -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).stopIssueDateLabel, -// border: const OutlineInputBorder(), -// suffixIcon: IconButton( -// icon: const Icon(Icons.calendar_today), -// onPressed: () => _selectDate(_stopIssueDateController), -// ), -// ), -// keyboardType: TextInputType.datetime, -// ), -// const SizedBox(height: 16), -// TextFormField( -// controller: _stopExpiryDateController, -// readOnly: true, -// onTap: () => _selectDate(_stopExpiryDateController), -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).stopExpiryDateLabel, -// border: const OutlineInputBorder(), -// suffixIcon: IconButton( -// icon: const Icon(Icons.calendar_today), -// onPressed: () => _selectDate(_stopExpiryDateController), -// ), -// ), -// keyboardType: TextInputType.datetime, -// ), -// const SizedBox(height: 16), -// TextFormField( -// controller: _stopAmountController, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).stopAmountHint, -// border: const OutlineInputBorder(), -// ), -// keyboardType: TextInputType.number, -// ), -// const SizedBox(height: 16), -// DropdownButtonFormField( -// value: _selectedComment, -// items: _commentOptions.map((String value) { -// return DropdownMenuItem( -// value: value, -// child: Text(value), -// ); -// }).toList(), -// onChanged: (newValue) { -// setState(() { -// _selectedComment = newValue; -// _showOtherCommentField = newValue == 'Other'; -// }); -// }, -// decoration: InputDecoration( -// labelText: AppLocalizations.of(context).stopCommentHint, -// border: const OutlineInputBorder(), -// ), -// ), -// if (_showOtherCommentField) -// Padding( -// padding: const EdgeInsets.only(top: 16.0), -// child: TextFormField( -// controller: _otherCommentController, -// decoration: const InputDecoration( -// labelText: "Other Reasons :", -// border: OutlineInputBorder(), -// ), -// validator: (value) { -// return null; -// }, -// ), -// ), -// const SizedBox(height: 16), -// TextFormField( -// initialValue: _formatDate(widget.date), -// readOnly: true, -// decoration: InputDecoration( -// labelText: -// AppLocalizations.of(context).chequebookIssueDateHint, -// border: const OutlineInputBorder(), -// ), -// ), -// const SizedBox(height: 32), -// ElevatedButton( -// onPressed: () { -// if (_formKey.currentState!.validate()) { -// Navigator.push( -// context, -// MaterialPageRoute( -// builder: (context) => TransactionPinScreen( -// onPinCompleted: (ctx, pin) async { -// Navigator.pop(context); -// try { -// final response = await _chequeService.revokeStop( -// accountno: widget.selectedAccount.accountNo!, -// stopFromChequeNo: -// _stopFromChequeNoController.text, -// instrType: widget.instrType, -// stopToChequeNo: -// _stopFromChequeNoController.text, -// stopIssueDate: _stopIssueDateController.text, -// stopExpiryDate: _stopExpiryDateController.text, -// stopAmount: _stopAmountController.text, -// stopComment: _selectedComment == 'Other' -// ? _otherCommentController.text -// : _selectedComment ?? '', -// chequeIssueDate: widget.date, -// tpin: pin, -// ); -// if (!mounted) return; -// final decodedResponse = jsonDecode(response); -// String responseString = response.toString(); // used as the case only for incorrect TPIN -// final status = decodedResponse['status']; -// final message = decodedResponse['message']; -// final code = decodedResponse['code']; -// if (status == 'SUCCESS') { -// _showResponseDialog('Success', message); -// } if (status == 'ERROR') { -// String errMessage = "error"; -// if(code == '0429') { -// errMessage = 'The selected Cheque is already stopped'; -// } else if(code == '0748') { -// errMessage = 'The selected Cheque is already presented'; -// } -// _showResponseDialog('Error', errMessage); -// } -// if(responseString.contains('INCORRECT_TPIN')){ -// _showResponseDialog('Invalid TPIN', -// 'The TPIN you entered is incorrect. Please try again.'); -// } -// } on DioException catch (e) { -// try { -// final errorBodyString = -// e.toString().split('Exception: ')[1]; -// final errorBody = jsonDecode(errorBodyString); -// if (errorBody.containsKey('error') && -// errorBody['error'] == 'INCORRECT_TPIN') { -// _showResponseDialog('Invalid TPIN', -// 'The TPIN you entered is incorrect. Please try again.'); -// } else { -// _showResponseDialog( -// 'Error', 'Internal Server Error'); -// } -// } catch (_) { -// _showResponseDialog( -// 'Error', 'Internal Server Error'); -// } -// } -// }, -// ), -// ), -// ); -// } -// }, -// child: Text("Revoke Stop"), -// ), -// ], -// ), -// ), -// ); -// } -// } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Revoke Single Stop")), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: ListView( + children: [ + Card( + elevation: 0, + margin: const EdgeInsets.symmetric(vertical: 8.0), + child: ListTile( + leading: Image.asset( + 'assets/images/logo.png', + width: 40, + height: 40, + ), + title: Text(widget.selectedAccount.accountNo!), + subtitle: + Text(AppLocalizations.of(context).accountNumberLabel), + ), + ), + const SizedBox(height: 24), + TextFormField( + controller: _stopFromChequeNoController, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).chequeNumberLabel, + border: const OutlineInputBorder(), + errorMaxLines: 2, + ), + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return AppLocalizations.of(context) + .pleaseEnterChequeNumberError; + } + final chequeNumber = int.tryParse(value); + final fromCheque = int.tryParse(widget.fromCheque); + final toCheque = int.tryParse(widget.toCheque); + if (chequeNumber == null || + fromCheque == null || + toCheque == null) { + return AppLocalizations.of(context) + .invalidChequeNumberFormatError; + } + // if (chequeNumber < fromCheque || chequeNumber > toCheque) { + // return AppLocalizations.of(context).chequeNumberRangeError( + // widget.fromCheque, widget.toCheque); + // } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + initialValue: widget.instrType, + readOnly: true, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).instrumentTypeLabel, + border: const OutlineInputBorder(), + ), + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopIssueDateController, + readOnly: true, + onTap: () => _selectDate(_stopIssueDateController), + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopIssueDateLabel, + border: const OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.calendar_today), + onPressed: () => _selectDate(_stopIssueDateController), + ), + ), + keyboardType: TextInputType.datetime, + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopExpiryDateController, + readOnly: true, + onTap: () => _selectDate(_stopExpiryDateController), + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopExpiryDateLabel, + border: const OutlineInputBorder(), + suffixIcon: IconButton( + icon: const Icon(Icons.calendar_today), + onPressed: () => _selectDate(_stopExpiryDateController), + ), + ), + keyboardType: TextInputType.datetime, + ), + const SizedBox(height: 16), + TextFormField( + controller: _stopAmountController, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopAmountHint, + border: const OutlineInputBorder(), + ), + keyboardType: TextInputType.number, + ), + const SizedBox(height: 16), + DropdownButtonFormField( + value: _selectedComment, + items: _commentOptions.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + _selectedComment = newValue; + _showOtherCommentField = newValue == 'Other'; + }); + }, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).stopCommentHint, + border: const OutlineInputBorder(), + ), + ), + if (_showOtherCommentField) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: TextFormField( + controller: _otherCommentController, + decoration: const InputDecoration( + labelText: "Other Reasons :", + border: OutlineInputBorder(), + ), + validator: (value) { + return null; + }, + ), + ), + const SizedBox(height: 32), + ElevatedButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TransactionPinScreen( + onPinCompleted: (ctx, pin) async { + Navigator.pop(context); + try { + final response = await _chequeService.revokeStop( + accountno: widget.selectedAccount.accountNo!, + removeFromChequeNo: + _stopFromChequeNoController.text, + instrType: widget.instrType, + removeToChequeNo: + _stopFromChequeNoController.text, + removeIssueDate: _stopIssueDateController.text, + removeExpiryDate: _stopExpiryDateController.text, + removeAmount: _stopAmountController.text, + removeComment: _selectedComment == 'Other' + ? _otherCommentController.text + : _selectedComment ?? '', + tpin: pin, + ); + if (!mounted) return; + final decodedResponse = jsonDecode(response); + String responseString = response.toString(); // used as the case only for incorrect TPIN + final status = decodedResponse['status']; + final message = decodedResponse['message']; + final code = decodedResponse['code']; + if (status == 'SUCCESS') { + _showResponseDialog('Success', message); + } if (status == 'ERROR') { + String errMessage = "error"; + if(code == '0429') { + errMessage = 'The selected Cheque is already stopped'; + } else if(code == '0748') { + errMessage = 'The selected Cheque is already presented'; + } + _showResponseDialog('Error', errMessage); + } + if(responseString.contains('INCORRECT_TPIN')){ + _showResponseDialog('Invalid TPIN', + 'The TPIN you entered is incorrect. Please try again.'); + } + } on DioException catch (e) { + try { + final errorBodyString = + e.toString().split('Exception: ')[1]; + final errorBody = jsonDecode(errorBodyString); + if (errorBody.containsKey('error') && + errorBody['error'] == 'INCORRECT_TPIN') { + _showResponseDialog('Invalid TPIN', + 'The TPIN you entered is incorrect. Please try again.'); + } else { + _showResponseDialog( + 'Error', 'Internal Server Error'); + } + } catch (_) { + _showResponseDialog( + 'Error', 'Internal Server Error'); + } + } + }, + ), + ), + ); + } + }, + child: Text("Revoke Stop"), + ), + ], + ), + ), + ), + ); + } +}