APY integrated without testing...

This commit is contained in:
2026-03-18 12:36:41 +05:30
parent 075cb3aaad
commit 8744e69ef7
29 changed files with 1069 additions and 498 deletions

View File

@@ -210,4 +210,125 @@ String? policystatus,
return null; return null;
} }
} }
Future<dynamic> fetchpapydetails({
required String accountno,
}) async {
try {
final response = await _dio.post(
"/api/apy/req/APY",
data: {
'accountNo': accountno,
},
options: Options(
headers: {
"Content-Type": "application/json",
},
),
);
log("PMY Details Response: ${response.data}");
if (response.statusCode == 200) {
return response.data;
} else {
throw Exception("INTERNAL SERVER ERROR");
}
} catch (e) {
log("Error fetching APY details: $e");
return null;
}
}
Future registerAPY({
String? accountno,
String? customerfirstname,
String? customermiddlename,
String? customerlastname,
String? availablebalance,
String? customerdob,
String? emailid,
String? gender,
String? married,
String? nomineename,
String? relationwithsubscriber,
String? mobilenumber,
String? nomineeminor,
String? customerno,
String? beneficaryofothersociatysecurityschemes,
String? whetherincometaxpayer,
String? customertitle,
String? aadharno,
String? nameofspouse,
String? ageofjoining,
String? pensionamtoptedfor,
String? montlycontributioncalculate,
String? collectionchannel,
String? subsequentContributionDebitDate,
String? secondnomineeminor,
String? secondnomineename,
String? secondrelationshipwithsubscriber,
String? pincode,
String? fatcacrsapplicable,
String? countryofbirth,
String? countryofcitizenship,
String? countryofresidencefortaxpurpose,
String? uspersonflag,
String? fatcadeclarationcount,
String? documentevidencingcitizenshipflag,
String? reasonfornoevidence,
String? nameofdocumentforcitizenshipevidence,
String? modeofcollection,
String? contributionType,
}) async {
final response = await _dio.post(
'/api/apy/create/APY',
options: Options(
validateStatus: (int? status) => true,
receiveDataWhenStatusError: true,
),
data: {
'accountno':accountno,
'customerfirstname':customerfirstname,
'customermiddlename':customermiddlename,
'customerlastname':customerlastname,
'availablebalance':availablebalance,
'customerdob':customerdob,
'emailid':emailid,
'gender':gender,
'married':married,
'nomineename':nomineename,
'relationwithsubscriber':relationwithsubscriber,
'mobilenumber':mobilenumber,
'nomineeminor':nomineeminor,
'customerno':customerno,
'beneficaryofothersociatysecurityschemes':beneficaryofothersociatysecurityschemes,
'whetherincometaxpayer':whetherincometaxpayer,
'customertitle':customertitle,
'aadharno':aadharno,
'nameofspouse':nameofspouse,
'ageofjoining':ageofjoining,
'pensionamtoptedfor':pensionamtoptedfor,
'montlycontributioncalculate':montlycontributioncalculate,
'collectionchannel':collectionchannel,
'subsequentContributionDebitDate':subsequentContributionDebitDate,
'secondnomineeminor':secondnomineeminor,
'secondnomineename':secondnomineename,
'secondrelationshipwithsubscriber':secondrelationshipwithsubscriber,
'pincode':pincode,
'fatcacrsapplicable':fatcacrsapplicable,
'countryofbirth':countryofbirth,
'countryofcitizenship':countryofcitizenship,
'countryofresidencefortaxpurpose':countryofresidencefortaxpurpose,
'uspersonflag':uspersonflag,
'fatcadeclarationcount':fatcadeclarationcount,
'documentevidencingcitizenshipflag':documentevidencingcitizenshipflag,
'reasonfornoevidence':reasonfornoevidence,
'nameofdocumentforcitizenshipevidence':nameofdocumentforcitizenshipevidence,
'modeofcollection':modeofcollection,
'contributionType':contributionType,
},
);
return response.toString();
}
} }

View File

@@ -78,7 +78,7 @@ Dio _createDioClient() {
final dio = Dio( final dio = Dio(
BaseOptions( BaseOptions(
baseUrl: 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 //'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), connectTimeout: const Duration(seconds: 60),

View File

@@ -16,7 +16,6 @@ class AccountOpeningScreen extends StatefulWidget {
} }
class _AccountOpeningScreenState extends State<AccountOpeningScreen> { class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -41,8 +40,7 @@ class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const FdScreen( builder: (context) => const FdScreen(),
),
), ),
); );
}, },
@@ -56,8 +54,7 @@ class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const TermDepositScreen() builder: (context) => const TermDepositScreen()),
),
); );
}, },
), ),
@@ -70,7 +67,8 @@ class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const RecurringDepositScreen() ), builder: (context) =>
const RecurringDepositScreen()),
); );
}, },
), ),
@@ -83,8 +81,7 @@ class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const LoanScreen() builder: (context) => const LoanScreen()),
),
); );
}, },
), ),
@@ -136,8 +133,7 @@ class AccountOpeningCardTile extends StatelessWidget {
), ),
elevation: 4, elevation: 4,
child: InkWell( child: InkWell(
onTap: onTap: disable ? null : onTap,
disable ? null : onTap,
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0), padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
@@ -172,4 +168,4 @@ class AccountOpeningCardTile extends StatelessWidget {
), ),
); );
} }
} }

View File

@@ -72,10 +72,9 @@ class _FdScreenState extends State<FdScreen> {
TextFormField( TextFormField(
controller: _amountController, controller: _amountController,
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Enter Amount', labelText: 'Enter Amount',
border: OutlineInputBorder(), border: OutlineInputBorder(),
prefixText: '' prefixText: ''),
),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
@@ -96,10 +95,8 @@ class _FdScreenState extends State<FdScreen> {
builder: (context) => const InterestRatesScreen()), builder: (context) => const InterestRatesScreen()),
); );
}, },
child: Text( child: Text('Interest Rates',
'Interest Rates', style: Theme.of(context).textTheme.titleSmall),
style: Theme.of(context).textTheme.titleSmall
),
), ),
], ],
), ),
@@ -228,7 +225,8 @@ class _FdScreenState extends State<FdScreen> {
// TODO: Implement proceed logic // TODO: Implement proceed logic
}, },
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 15), padding:
const EdgeInsets.symmetric(horizontal: 40, vertical: 15),
), ),
child: const Text( child: const Text(
'Proceed', 'Proceed',
@@ -241,4 +239,4 @@ class _FdScreenState extends State<FdScreen> {
), ),
); );
} }
} }

View File

@@ -14,4 +14,4 @@ class InterestRatesScreen extends StatelessWidget {
), ),
); );
} }
} }

View File

@@ -12,7 +12,7 @@ class LoanScreen extends StatelessWidget {
title: const Text("Request Loan"), title: const Text("Request Loan"),
), ),
body: const Center( body: const Center(
child: Text("Loan Account"), child: Text("Loan Account"),
), ),
); );
} }

View File

@@ -12,7 +12,7 @@ class RecurringDepositScreen extends StatelessWidget {
title: const Text("Recurring Deposit"), title: const Text("Recurring Deposit"),
), ),
body: const Center( body: const Center(
child: Text("Recurring Deposit"), child: Text("Recurring Deposit"),
), ),
); );
} }

View File

@@ -16,4 +16,4 @@ class TermDepositScreen extends StatelessWidget {
), ),
); );
} }
} }

View File

@@ -187,7 +187,8 @@ class _BeneficiaryDetailsScreenState extends State<BeneficiaryDetailsScreen> {
CircleAvatar( CircleAvatar(
radius: 24, radius: 24,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
child: getBankLogo(widget.beneficiary.bankName, context), child:
getBankLogo(widget.beneficiary.bankName, context),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Text( Text(
@@ -274,4 +275,3 @@ class _BeneficiaryDetailsScreenState extends State<BeneficiaryDetailsScreen> {
); );
} }
} }

View File

@@ -149,7 +149,6 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: hintText:
AppLocalizations.of(context).searchByNameOrAccountHint, AppLocalizations.of(context).searchByNameOrAccountHint,
prefixIcon: const Icon(Icons.search), prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),

View File

@@ -93,7 +93,8 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
), ),
Expanded( Expanded(
child: ChequeManagementCardTile( child: ChequeManagementCardTile(
icon: Symbols.check_circle, // Using check_circle for Positive Pay icon: Symbols
.check_circle, // Using check_circle for Positive Pay
label: AppLocalizations.of(context).positivePayTitle, label: AppLocalizations.of(context).positivePayTitle,
onTap: () { onTap: () {
Navigator.push( Navigator.push(
@@ -191,4 +192,4 @@ class ChequeManagementCardTile extends StatelessWidget {
), ),
); );
} }
} }

View File

@@ -36,7 +36,7 @@ class _PositivePayScreenState extends State<PositivePayScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_filteredUsers = widget.users _filteredUsers = widget.users
.where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType)) .where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType))
.toList(); .toList();
// Pre-fill the account number if possible // Pre-fill the account number if possible
@@ -113,7 +113,7 @@ class _PositivePayScreenState extends State<PositivePayScreen> {
super.dispose(); super.dispose();
} }
Future<void> _showResponseDialog(String title, String message) async { Future<void> _showResponseDialog(String title, String message) async {
return showDialog<void>( return showDialog<void>(
context: context, context: context,
barrierDismissible: false, // user must tap button! barrierDismissible: false, // user must tap button!
@@ -145,7 +145,8 @@ Future<void> _showResponseDialog(String title, String message) async {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text( title: Text(
AppLocalizations.of(context).positivePay, // Will be replaced by localization AppLocalizations.of(context)
.positivePay, // Will be replaced by localization
), ),
centerTitle: false, centerTitle: false,
), ),
@@ -199,12 +200,13 @@ Future<void> _showResponseDialog(String title, String message) async {
final fromCheque = int.tryParse(_ciFromCheque ?? ''); final fromCheque = int.tryParse(_ciFromCheque ?? '');
final toCheque = int.tryParse(_ciToCheque ?? ''); final toCheque = int.tryParse(_ciToCheque ?? '');
if (chequeNumber == null) { if (chequeNumber == null) {
return AppLocalizations.of(context).invalidChequeNumberFormatError; return AppLocalizations.of(context)
.invalidChequeNumberFormatError;
} }
if (fromCheque != null && toCheque != null) { if (fromCheque != null && toCheque != null) {
if (chequeNumber < fromCheque || chequeNumber > toCheque) { if (chequeNumber < fromCheque || chequeNumber > toCheque) {
return AppLocalizations.of(context).chequeNumberRangeError( return AppLocalizations.of(context)
_ciFromCheque!, _ciToCheque!); .chequeNumberRangeError(_ciFromCheque!, _ciToCheque!);
} }
} }
return null; return null;
@@ -228,13 +230,15 @@ Future<void> _showResponseDialog(String title, String message) async {
); );
if (pickedDate != null) { if (pickedDate != null) {
// Format the date as you wish // Format the date as you wish
String formattedDate = "${pickedDate.year}-${pickedDate.month.toString().padLeft(2, '0')}-${pickedDate.day.toString().padLeft(2, '0')}"; String formattedDate =
"${pickedDate.year}-${pickedDate.month.toString().padLeft(2, '0')}-${pickedDate.day.toString().padLeft(2, '0')}";
_chequeDateController.text = formattedDate; _chequeDateController.text = formattedDate;
} }
}, },
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return AppLocalizations.of(context).pleaseSelectChequeIssuedDate; return AppLocalizations.of(context)
.pleaseSelectChequeIssuedDate;
} }
return null; return null;
}, },
@@ -255,7 +259,8 @@ Future<void> _showResponseDialog(String title, String message) async {
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
prefixText: '', prefixText: '',
), ),
keyboardType: const TextInputType.numberWithOptions(decimal: true), keyboardType:
const TextInputType.numberWithOptions(decimal: true),
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return AppLocalizations.of(context).pleaseEnterAmount; return AppLocalizations.of(context).pleaseEnterAmount;
@@ -277,34 +282,34 @@ Future<void> _showResponseDialog(String title, String message) async {
try { try {
final response = await _chequeService.registerPPS( final response = await _chequeService.registerPPS(
cheque_no: _chequeNumberController.text, cheque_no: _chequeNumberController.text,
account_number: account_number: _selectedAccount!.accountNo!,
_selectedAccount!.accountNo!, issue_date: _chequeDateController.text,
issue_date:
_chequeDateController.text,
amount: _amountController.text, amount: _amountController.text,
payee_name: _payeeController.text, payee_name: _payeeController.text,
tpin: pin, tpin: pin,
); );
if (!mounted) return; if (!mounted) return;
String responseString = response.toString(); String responseString = response.toString();
if(responseString == 'PPS Registered Successfully'){ if (responseString ==
'PPS Registered Successfully') {
_showResponseDialog('REGISTRATION SUCCESFUL', _showResponseDialog('REGISTRATION SUCCESFUL',
'Your Positive Pay Request has been registered succesfully'); 'Your Positive Pay Request has been registered succesfully');
} }
if(responseString.contains('Cheque already registered')){ if (responseString
.contains('Cheque already registered')) {
_showResponseDialog('ERROR', _showResponseDialog('ERROR',
'Your Request for the selected cheque number has already been registered'); 'Your Request for the selected cheque number has already been registered');
} }
if(responseString.contains('INCORRECT_TPIN')){ if (responseString.contains('INCORRECT_TPIN')) {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');
} }
} on DioException catch (e) { } on DioException catch (e) {
try { try {
final errorBodyString = final errorBodyString =
e.toString().split('Exception: ')[1]; e.toString().split('Exception: ')[1];
final errorBody = jsonDecode(errorBodyString); final errorBody = jsonDecode(errorBodyString);
if (errorBody.containsKey('error') && if (errorBody.containsKey('error') &&
errorBody['error'] == 'INCORRECT_TPIN') { errorBody['error'] == 'INCORRECT_TPIN') {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');

View File

@@ -27,7 +27,8 @@ class RevokeStopMultipleChequesScreen extends StatefulWidget {
_RevokeStopMultipleChequesScreenState(); _RevokeStopMultipleChequesScreenState();
} }
class _RevokeStopMultipleChequesScreenState extends State<RevokeStopMultipleChequesScreen> { class _RevokeStopMultipleChequesScreenState
extends State<RevokeStopMultipleChequesScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _stopFromChequeNoController = TextEditingController(); final _stopFromChequeNoController = TextEditingController();
final _stopToChequeNoController = TextEditingController(); final _stopToChequeNoController = TextEditingController();
@@ -275,7 +276,8 @@ class _RevokeStopMultipleChequesScreenState extends State<RevokeStopMultipleCheq
removeToChequeNo: removeToChequeNo:
_stopToChequeNoController.text, _stopToChequeNoController.text,
removeIssueDate: _stopIssueDateController.text, removeIssueDate: _stopIssueDateController.text,
removeExpiryDate: _stopExpiryDateController.text, removeExpiryDate:
_stopExpiryDateController.text,
removeAmount: _stopAmountController.text, removeAmount: _stopAmountController.text,
removeComment: _selectedComment == 'Other' removeComment: _selectedComment == 'Other'
? _otherCommentController.text ? _otherCommentController.text
@@ -284,24 +286,28 @@ class _RevokeStopMultipleChequesScreenState extends State<RevokeStopMultipleCheq
); );
if (!mounted) return; if (!mounted) return;
final decodedResponse = jsonDecode(response); final decodedResponse = jsonDecode(response);
String responseString = response.toString(); // used as the case only for incorrect TPIN String responseString = response
.toString(); // used as the case only for incorrect TPIN
final status = decodedResponse['status']; final status = decodedResponse['status'];
final message = decodedResponse['message']; final message = decodedResponse['message'];
final code = decodedResponse['code']; final code = decodedResponse['code'];
if (status == 'SUCCESS') { if (status == 'SUCCESS') {
_showResponseDialog('Success', message); _showResponseDialog('Success', message);
} if (status == 'ERROR') { }
if (status == 'ERROR') {
String errMessage = "error"; String errMessage = "error";
if(code == '0172') { if (code == '0172') {
errMessage = 'The selected Cheque is not stopped'; errMessage =
} else if(code == '0748') { 'The selected Cheque is not stopped';
errMessage = 'The selected Cheque is already presented'; } else if (code == '0748') {
errMessage =
'The selected Cheque is already presented';
} }
_showResponseDialog('Error', errMessage); _showResponseDialog('Error', errMessage);
} }
if(responseString.contains('INCORRECT_TPIN')){ if (responseString.contains('INCORRECT_TPIN')) {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');
} }
} on Exception catch (e) { } on Exception catch (e) {
try { try {

View File

@@ -10,12 +10,11 @@ class RevokeStopChequeScreen extends StatefulWidget {
final List<User> users; final List<User> users;
final int selectedIndex; final int selectedIndex;
const RevokeStopChequeScreen( const RevokeStopChequeScreen({
{ super.key,
super.key, required this.users,
required this.users, required this.selectedIndex,
required this.selectedIndex, });
});
@override @override
State<RevokeStopChequeScreen> createState() => _RevokeStopChequeScreenState(); State<RevokeStopChequeScreen> createState() => _RevokeStopChequeScreenState();
@@ -199,8 +198,10 @@ class _RevokeStopChequeScreenState extends State<RevokeStopChequeScreen> {
selectedAccount: _selectedAccount!, selectedAccount: _selectedAccount!,
date: _stCheques.first.Date!, date: _stCheques.first.Date!,
instrType: _stCheques.first.InstrType!, instrType: _stCheques.first.InstrType!,
fromCheque: _ciFromCheque ?? _stCheques.first.fromCheque!, fromCheque: _ciFromCheque ??
toCheque: _ciToCheque ?? _stCheques.first.toCheque!, _stCheques.first.fromCheque!,
toCheque:
_ciToCheque ?? _stCheques.first.toCheque!,
), ),
), ),
); );
@@ -216,7 +217,8 @@ class _RevokeStopChequeScreenState extends State<RevokeStopChequeScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Center( child: Center(
child: Text( child: Text(
AppLocalizations.of(context).revokeSingleStopTitle, AppLocalizations.of(context)
.revokeSingleStopTitle,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
@@ -248,8 +250,10 @@ class _RevokeStopChequeScreenState extends State<RevokeStopChequeScreen> {
selectedAccount: _selectedAccount!, selectedAccount: _selectedAccount!,
date: _stCheques.first.Date!, date: _stCheques.first.Date!,
instrType: _stCheques.first.InstrType!, instrType: _stCheques.first.InstrType!,
fromCheque: _ciFromCheque ?? _stCheques.first.fromCheque!, fromCheque: _ciFromCheque ??
toCheque: _ciToCheque ?? _stCheques.first.toCheque!, _stCheques.first.fromCheque!,
toCheque:
_ciToCheque ?? _stCheques.first.toCheque!,
), ),
), ),
); );
@@ -266,7 +270,7 @@ class _RevokeStopChequeScreenState extends State<RevokeStopChequeScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Center( child: Center(
child: Text( child: Text(
AppLocalizations.of(context).revokeMultipleStops, AppLocalizations.of(context).revokeMultipleStops,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,

View File

@@ -23,10 +23,12 @@ class RevokeStopSingleChequeScreen extends StatefulWidget {
required this.toCheque}); required this.toCheque});
@override @override
State<RevokeStopSingleChequeScreen> createState() => _RevokeStopSingleChequeScreenState(); State<RevokeStopSingleChequeScreen> createState() =>
_RevokeStopSingleChequeScreenState();
} }
class _RevokeStopSingleChequeScreenState extends State<RevokeStopSingleChequeScreen> { class _RevokeStopSingleChequeScreenState
extends State<RevokeStopSingleChequeScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _stopFromChequeNoController = TextEditingController(); final _stopFromChequeNoController = TextEditingController();
final _stopIssueDateController = TextEditingController(); final _stopIssueDateController = TextEditingController();
@@ -89,7 +91,7 @@ class _RevokeStopSingleChequeScreenState extends State<RevokeStopSingleChequeScr
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(AppLocalizations.of(context).revokeSingleStopTitle)), title: Text(AppLocalizations.of(context).revokeSingleStopTitle)),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Form( child: Form(
@@ -241,7 +243,8 @@ class _RevokeStopSingleChequeScreenState extends State<RevokeStopSingleChequeScr
removeToChequeNo: removeToChequeNo:
_stopFromChequeNoController.text, _stopFromChequeNoController.text,
removeIssueDate: _stopIssueDateController.text, removeIssueDate: _stopIssueDateController.text,
removeExpiryDate: _stopExpiryDateController.text, removeExpiryDate:
_stopExpiryDateController.text,
removeAmount: _stopAmountController.text, removeAmount: _stopAmountController.text,
removeComment: _selectedComment == 'Other' removeComment: _selectedComment == 'Other'
? _otherCommentController.text ? _otherCommentController.text
@@ -250,31 +253,35 @@ class _RevokeStopSingleChequeScreenState extends State<RevokeStopSingleChequeScr
); );
if (!mounted) return; if (!mounted) return;
final decodedResponse = jsonDecode(response); final decodedResponse = jsonDecode(response);
String responseString = response.toString(); // used as the case only for incorrect TPIN String responseString = response
.toString(); // used as the case only for incorrect TPIN
final status = decodedResponse['status']; final status = decodedResponse['status'];
final message = decodedResponse['message']; final message = decodedResponse['message'];
final code = decodedResponse['code']; final code = decodedResponse['code'];
if (status == 'SUCCESS') { if (status == 'SUCCESS') {
_showResponseDialog('Success', message); _showResponseDialog('Success', message);
} if (status == 'ERROR') { }
if (status == 'ERROR') {
String errMessage = "error"; String errMessage = "error";
if(code == '0172') { if (code == '0172') {
errMessage = 'The selected Cheque is not stopped'; errMessage =
} else if(code == '0748') { 'The selected Cheque is not stopped';
errMessage = 'The selected Cheque is already presented'; } else if (code == '0748') {
errMessage =
'The selected Cheque is already presented';
} }
_showResponseDialog('Error', errMessage); _showResponseDialog('Error', errMessage);
} }
if(responseString.contains('INCORRECT_TPIN')){ if (responseString.contains('INCORRECT_TPIN')) {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');
} }
} on DioException catch (e) { } on DioException catch (e) {
try { try {
final errorBodyString = final errorBodyString =
e.toString().split('Exception: ')[1]; e.toString().split('Exception: ')[1];
final errorBody = jsonDecode(errorBodyString); final errorBody = jsonDecode(errorBodyString);
if (errorBody.containsKey('error') && if (errorBody.containsKey('error') &&
errorBody['error'] == 'INCORRECT_TPIN') { errorBody['error'] == 'INCORRECT_TPIN') {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');

View File

@@ -309,24 +309,28 @@ class _StopMultipleChequesScreenState extends State<StopMultipleChequesScreen> {
); );
if (!mounted) return; if (!mounted) return;
final decodedResponse = jsonDecode(response); final decodedResponse = jsonDecode(response);
String responseString = response.toString(); // used as the case only for incorrect TPIN String responseString = response
.toString(); // used as the case only for incorrect TPIN
final status = decodedResponse['status']; final status = decodedResponse['status'];
final message = decodedResponse['message']; final message = decodedResponse['message'];
final code = decodedResponse['code']; final code = decodedResponse['code'];
if (status == 'SUCCESS') { if (status == 'SUCCESS') {
_showResponseDialog('Success', message); _showResponseDialog('Success', message);
} if (status == 'ERROR') { }
if (status == 'ERROR') {
String errMessage = "error"; String errMessage = "error";
if(code == '0429') { if (code == '0429') {
errMessage = 'The selected Cheque is already stopped'; errMessage =
} else if(code == '0748') { 'The selected Cheque is already stopped';
errMessage = 'The selected Cheque is already presented'; } else if (code == '0748') {
errMessage =
'The selected Cheque is already presented';
} }
_showResponseDialog('Error', errMessage); _showResponseDialog('Error', errMessage);
} }
if(responseString.contains('INCORRECT_TPIN')){ if (responseString.contains('INCORRECT_TPIN')) {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');
} }
} on Exception catch (e) { } on Exception catch (e) {
try { try {

View File

@@ -278,31 +278,35 @@ class _StopSingleChequeScreenState extends State<StopSingleChequeScreen> {
); );
if (!mounted) return; if (!mounted) return;
final decodedResponse = jsonDecode(response); final decodedResponse = jsonDecode(response);
String responseString = response.toString(); // used as the case only for incorrect TPIN String responseString = response
.toString(); // used as the case only for incorrect TPIN
final status = decodedResponse['status']; final status = decodedResponse['status'];
final message = decodedResponse['message']; final message = decodedResponse['message'];
final code = decodedResponse['code']; final code = decodedResponse['code'];
if (status == 'SUCCESS') { if (status == 'SUCCESS') {
_showResponseDialog('Success', message); _showResponseDialog('Success', message);
} if (status == 'ERROR') { }
if (status == 'ERROR') {
String errMessage = "error"; String errMessage = "error";
if(code == '0429') { if (code == '0429') {
errMessage = 'The selected Cheque is already stopped'; errMessage =
} else if(code == '0748') { 'The selected Cheque is already stopped';
errMessage = 'The selected Cheque is already presented'; } else if (code == '0748') {
errMessage =
'The selected Cheque is already presented';
} }
_showResponseDialog('Error', errMessage); _showResponseDialog('Error', errMessage);
} }
if(responseString.contains('INCORRECT_TPIN')){ if (responseString.contains('INCORRECT_TPIN')) {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');
} }
} on DioException catch (e) { } on DioException catch (e) {
try { try {
final errorBodyString = final errorBodyString =
e.toString().split('Exception: ')[1]; e.toString().split('Exception: ')[1];
final errorBody = jsonDecode(errorBodyString); final errorBody = jsonDecode(errorBodyString);
if (errorBody.containsKey('error') && if (errorBody.containsKey('error') &&
errorBody['error'] == 'INCORRECT_TPIN') { errorBody['error'] == 'INCORRECT_TPIN') {
_showResponseDialog('Invalid TPIN', _showResponseDialog('Invalid TPIN',
'The TPIN you entered is incorrect. Please try again.'); 'The TPIN you entered is incorrect. Please try again.');

View File

@@ -636,18 +636,20 @@ class _DashboardScreenState extends State<DashboardScreen>
ManageBeneficiariesScreen( ManageBeneficiariesScreen(
customerName: currAccount.name!))); customerName: currAccount.name!)));
}, disable: false), }, disable: false),
_buildQuickLink(Symbols.family_group, _buildQuickLink(
AppLocalizations.of(context).governmentSchemes, () { Symbols.family_group,
Navigator.push( AppLocalizations.of(context).governmentSchemes,
context, () {
MaterialPageRoute( Navigator.push(
builder: (context) => GovSchemeScreen( context,
users: users, MaterialPageRoute(
selectedIndex: selectedAccountIndex, builder: (context) => GovSchemeScreen(
))); users: users,
}, selectedIndex: selectedAccountIndex,
disable: isPaymentDisabled, )));
), },
disable: isPaymentDisabled,
),
_buildQuickLink( _buildQuickLink(
Symbols.checkbook, Symbols.checkbook,
AppLocalizations.of(context).chequeManagement, AppLocalizations.of(context).chequeManagement,

View File

@@ -78,7 +78,7 @@ class _ServiceScreen extends State<ServiceScreen> {
// label: "Account Opening", // label: "Account Opening",
// onTap: () { // onTap: () {
// Navigator.push( // Navigator.push(
// context, // context,
// MaterialPageRoute( // MaterialPageRoute(
// builder: (context) => const AccountOpeningScreen())); // builder: (context) => const AccountOpeningScreen()));
// }, // },
@@ -91,7 +91,7 @@ class _ServiceScreen extends State<ServiceScreen> {
// label: AppLocalizations.of(context).cardManagement, // label: AppLocalizations.of(context).cardManagement,
// onTap: () { // onTap: () {
// Navigator.push( // Navigator.push(
// context, // context,
// MaterialPageRoute( // MaterialPageRoute(
// builder: (context) => const CardManagementScreen())); // builder: (context) => const CardManagementScreen()));
// }, // },
@@ -110,8 +110,8 @@ class _ServiceScreen extends State<ServiceScreen> {
}, },
disabled: false, disabled: false,
), ),
), ),
// No Spacer() needed here as Expanded children will fill space // No Spacer() needed here as Expanded children will fill space
], ],
), ),
), ),
@@ -162,33 +162,34 @@ class ServiceManagementTile extends StatelessWidget {
onTap: onTap:
disabled ? null : onTap, // Disable InkWell if the tile is disabled disabled ? null : onTap, // Disable InkWell if the tile is disabled
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
child: Center( child: Center(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
icon, icon,
size: 48, // Make icon larger size: 48, // Make icon larger
color: color: disabled
disabled ? theme.disabledColor : theme.colorScheme.primary, ? theme.disabledColor
: theme.colorScheme.primary,
),
const SizedBox(height: 12),
Text(
label,
textAlign: TextAlign.center,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
color: disabled
? theme.disabledColor
: theme.colorScheme.onSurface,
), ),
const SizedBox(height: 12), ),
Text( ],
label,
textAlign: TextAlign.center,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
color: disabled
? theme.disabledColor
: theme.colorScheme.onSurface,
),
),
],
),
), ),
), ),
), ),
),
); );
} }
} }

View File

@@ -1,4 +1,8 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:kmobile/api/services/yojna_service.dart';
import 'package:kmobile/di/injection.dart';
import 'package:kmobile/l10n/app_localizations.dart'; import 'package:kmobile/l10n/app_localizations.dart';
class APYRegisterScreen extends StatefulWidget { class APYRegisterScreen extends StatefulWidget {
@@ -12,42 +16,73 @@ class APYRegisterScreen extends StatefulWidget {
class _APYRegisterScreenState extends State<APYRegisterScreen> { class _APYRegisterScreenState extends State<APYRegisterScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
// Controllers // Helper to format initial date string (DDMMYYYY -> DD/MM/YYYY)
late final _titleController = TextEditingController(text: widget.initialData?['customertitle']?.toString()); String _formatInitialDate(dynamic date) {
late final _firstNameController = TextEditingController(text: widget.initialData?['customerfirstname']?.toString()); if (date == null) return '';
late final _middleNameController = TextEditingController(text: widget.initialData?['customermiddlename']?.toString()); String dateStr = date.toString();
late final _lastNameController = TextEditingController(text: widget.initialData?['customerlastname']?.toString()); if (dateStr.length == 8) {
late final _customerNoController = TextEditingController(text: widget.initialData?['customerno']?.toString()); return "${dateStr.substring(0, 2)}/${dateStr.substring(2, 4)}/${dateStr.substring(4)}";
late final _accountNoController = TextEditingController(text: widget.initialData?['accountno']?.toString()); }
late final _balanceController = TextEditingController(text: widget.initialData?['availablebalance']?.toString()); return dateStr;
late final _dobController = TextEditingController(text: widget.initialData?['customerdob']?.toString()); }
late final _genderController = TextEditingController(text: widget.initialData?['gender']?.toString());
late final _marriedController = TextEditingController(text: widget.initialData?['married']?.toString());
late final _mobileController = TextEditingController(text: widget.initialData?['mobilenumber']?.toString());
late final _emailController = TextEditingController(text: widget.initialData?['emailid']?.toString());
late final _aadhaarController = TextEditingController(text: widget.initialData?['aadharno']?.toString());
late final _pincodeController = TextEditingController(text: widget.initialData?['pincode']?.toString());
late final _pensionAmountController = TextEditingController(text: widget.initialData?['pensionamtoptedfor']?.toString() ?? '1000'); // Controllers initialized strictly from initialData where available, otherwise empty.
late final _ageOfJoiningController = TextEditingController(text: widget.initialData?['ageofjoining']?.toString()); late final _titleController = TextEditingController(
late final _spouseNameController = TextEditingController(text: widget.initialData?['nameofspouse']?.toString()); text: widget.initialData?['customertitle']?.toString());
late final _incomeTaxPayerController = TextEditingController(text: widget.initialData?['whetherincometaxpayer']?.toString()); late final _firstNameController = TextEditingController(
late final _otherSchemeController = TextEditingController(text: widget.initialData?['beneficaryofothersociatysecurityschemes']?.toString()); text: widget.initialData?['customerfirstname']?.toString());
late final _collectionChannelController = TextEditingController(text: widget.initialData?['collectionchannel']?.toString() ?? '1'); late final _middleNameController = TextEditingController(
late final _contributionTypeController = TextEditingController(text: widget.initialData?['contributionType']?.toString() ?? 'C'); text: widget.initialData?['customermiddlename']?.toString());
late final _debitDateController = TextEditingController(text: widget.initialData?['subsequentContributionDebitDate']?.toString()); late final _lastNameController = TextEditingController(
text: widget.initialData?['customerlastname']?.toString());
late final _customerNoController = TextEditingController(
text: widget.initialData?['customerno']?.toString());
late final _accountNoController = TextEditingController(
text: widget.initialData?['accountno']?.toString());
late final _balanceController = TextEditingController(
text: widget.initialData?['availablebalance']?.toString());
late final _dobController = TextEditingController(
text: _formatInitialDate(widget.initialData?['customerdob']));
late final _genderController = TextEditingController(
text: widget.initialData?['gender']?.toString());
late final _aadhaarController = TextEditingController(
text: widget.initialData?['aadharno']?.toString());
late final _ageOfJoiningController = TextEditingController(
text: widget.initialData?['ageofjoining']?.toString());
late final _emailController = TextEditingController(
text: widget.initialData?['emailid']?.toString());
late final _modeOfCollectionController = TextEditingController(
text: widget.initialData?['modeofcollection']?.toString());
late final _nomineeNameController = TextEditingController(text: widget.initialData?['nomineename']?.toString()); // Fields that must be filled by the user (no defaults)
late final _nomineeRelationController = TextEditingController(text: widget.initialData?['relationwithsubscriber']?.toString()); late final _marriedController = TextEditingController();
late final _nomineeMinorController = TextEditingController(text: widget.initialData?['nomineeminor']?.toString() ?? 'N'); late final _mobileController = TextEditingController();
late final _pincodeController = TextEditingController();
late final _pensionAmountController = TextEditingController();
late final _spouseNameController = TextEditingController();
late final _incomeTaxPayerController = TextEditingController();
late final _otherSchemeController = TextEditingController();
late final _collectionChannelController = TextEditingController();
late final _contributionTypeController = TextEditingController();
late final _debitDateController = TextEditingController();
late final _nomineeNameController = TextEditingController();
late final _nomineeRelationController = TextEditingController();
late final _nomineeMinorController = TextEditingController();
late final _nomineeDobController = TextEditingController(); late final _nomineeDobController = TextEditingController();
late final _guardianNameController = TextEditingController(); late final _guardianNameController = TextEditingController();
late final _fatcaController = TextEditingController();
late final _birthCountryController = TextEditingController();
late final _citizenshipCountryController = TextEditingController();
late final _taxResidenceCountryController = TextEditingController();
late final _usPersonController = TextEditingController();
late final _fatcaController = TextEditingController(text: widget.initialData?['fatcacrsapplicable']?.toString()); late final _secondNomineeNameController = TextEditingController();
late final _birthCountryController = TextEditingController(text: widget.initialData?['countryofbirth']?.toString()); late final _secondNomineeMinorController = TextEditingController();
late final _citizenshipCountryController = TextEditingController(text: widget.initialData?['countryofcitizenship']?.toString()); late final _secondNomineeRelationController = TextEditingController();
late final _taxResidenceCountryController = TextEditingController(text: widget.initialData?['countryofresidencefortaxpurpose']?.toString()); late final _fatcaCountController = TextEditingController();
late final _usPersonController = TextEditingController(text: widget.initialData?['uspersonflag']?.toString()); late final _docCitizenshipFlagController = TextEditingController();
late final _reasonNoEvidenceController = TextEditingController();
late final _docNameEvidenceController = TextEditingController();
final Map<String, String> _yesNoOptions = { final Map<String, String> _yesNoOptions = {
'Y': 'Yes', 'Y': 'Yes',
@@ -60,6 +95,12 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
'03': 'Miss', '03': 'Miss',
}; };
final Map<String, String> _genderOptions = {
'M': 'Male',
'F': 'Female',
'O': 'Other',
};
final Map<String, String> _pensionOptions = { final Map<String, String> _pensionOptions = {
'1000': '₹1000', '1000': '₹1000',
'2000': '₹2000', '2000': '₹2000',
@@ -143,20 +184,121 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
_citizenshipCountryController.dispose(); _citizenshipCountryController.dispose();
_taxResidenceCountryController.dispose(); _taxResidenceCountryController.dispose();
_usPersonController.dispose(); _usPersonController.dispose();
_secondNomineeNameController.dispose();
_secondNomineeMinorController.dispose();
_secondNomineeRelationController.dispose();
_fatcaCountController.dispose();
_docCitizenshipFlagController.dispose();
_reasonNoEvidenceController.dispose();
_docNameEvidenceController.dispose();
_modeOfCollectionController.dispose();
super.dispose(); super.dispose();
} }
bool _isFetched(String key) { Future<void> _selectDate(BuildContext context, TextEditingController controller) async {
return widget.initialData != null && final DateTime? picked = await showDatePicker(
widget.initialData!.containsKey(key) && context: context,
widget.initialData![key]?.toString().isNotEmpty == true; initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
if (picked != null) {
setState(() {
// Display format: DD/MM/YYYY
controller.text = DateFormat('dd/MM/yyyy').format(picked);
});
}
} }
void _handleRegister() { void _handleRegister() async {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar( showDialog(
const SnackBar(content: Text('Registration logic to be implemented')), context: context,
barrierDismissible: false,
builder: (context) => const Center(child: CircularProgressIndicator()),
); );
try {
final yojnaService = getIt<YojnaService>();
final response = await yojnaService.registerAPY(
accountno: _accountNoController.text,
customerfirstname: _firstNameController.text,
customermiddlename: _middleNameController.text,
customerlastname: _lastNameController.text,
availablebalance: _balanceController.text,
// Remove slashes for API (DD/MM/YYYY -> DDMMYYYY)
customerdob: _dobController.text.replaceAll('/', ''),
emailid: _emailController.text,
gender: _genderController.text,
married: _marriedController.text,
nomineename: _nomineeNameController.text,
relationwithsubscriber: _nomineeRelationController.text,
mobilenumber: _mobileController.text,
nomineeminor: _nomineeMinorController.text,
customerno: _customerNoController.text,
beneficaryofothersociatysecurityschemes: _otherSchemeController.text,
whetherincometaxpayer: _incomeTaxPayerController.text,
customertitle: _titleController.text,
aadharno: _aadhaarController.text,
nameofspouse: _spouseNameController.text,
ageofjoining: _ageOfJoiningController.text,
pensionamtoptedfor: _pensionAmountController.text,
montlycontributioncalculate: _calculatedContribution,
collectionchannel: _collectionChannelController.text,
// Remove slashes for API
subsequentContributionDebitDate: _debitDateController.text.replaceAll('/', ''),
secondnomineeminor: _secondNomineeMinorController.text,
secondnomineename: _secondNomineeNameController.text,
secondrelationshipwithsubscriber: _secondNomineeRelationController.text,
pincode: _pincodeController.text,
fatcacrsapplicable: _fatcaController.text,
countryofbirth: _birthCountryController.text,
countryofcitizenship: _citizenshipCountryController.text,
countryofresidencefortaxpurpose: _taxResidenceCountryController.text,
uspersonflag: _usPersonController.text,
fatcadeclarationcount: _fatcaCountController.text,
documentevidencingcitizenshipflag: _docCitizenshipFlagController.text,
reasonfornoevidence: _reasonNoEvidenceController.text,
nameofdocumentforcitizenshipevidence: _docNameEvidenceController.text,
modeofcollection: _modeOfCollectionController.text,
contributionType: _contributionTypeController.text,
);
if (!mounted) return;
Navigator.pop(context); // Close loading dialog
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Registration Result'),
content: SingleChildScrollView(
child: Text(response.toString()),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'),
),
],
),
);
} catch (e) {
if (!mounted) return;
Navigator.pop(context); // Close loading dialog
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Error'),
content: Text('Failed to register: $e'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'),
),
],
),
);
}
} }
} }
@@ -174,7 +316,7 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
// Tile 1: Customer & APY Details // Tile 1: Customer Details
Card( Card(
elevation: 2, elevation: 2,
child: Padding( child: Padding(
@@ -182,53 +324,104 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(l10n.details, Text(l10n.personaldetails,
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)), fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildDropdownField(_titleController, l10n.customerTitle, _buildDropdownField(
_titleOptions, _titleController, l10n.customerTitle, _titleOptions),
readOnly: _isFetched('customertitle')),
_buildTextField( _buildTextField(
_firstNameController, l10n.customerFirstName, _firstNameController, l10n.customerFirstName),
readOnly: _isFetched('customerfirstname')),
_buildTextField( _buildTextField(
_middleNameController, l10n.customerMiddleName, _middleNameController, l10n.customerMiddleName),
readOnly: _isFetched('customermiddlename')),
_buildTextField( _buildTextField(
_lastNameController, l10n.customerLastName, _lastNameController, l10n.customerLastName),
readOnly: _isFetched('customerlastname')), _buildTextField(_customerNoController, l10n.customerNo),
_buildTextField(_accountNoController, l10n.accountNumber, _buildTextField(_accountNoController, l10n.accountNumber,
keyboardType: TextInputType.number, keyboardType: TextInputType.number),
readOnly: _isFetched('accountno')), _buildTextField(_balanceController, l10n.availableBalance,
_buildTextField( keyboardType: TextInputType.number),
_balanceController, l10n.availableBalance,
keyboardType: TextInputType.number,
readOnly: _isFetched('availablebalance')),
_buildTextField(_dobController, l10n.customerDobFormat, _buildTextField(_dobController, l10n.customerDobFormat,
mandatory: true, readOnly: _isFetched('customerdob')), mandatory: true, onTap: () => _selectDate(context, _dobController)),
_buildDropdownField(
_genderController, l10n.gender, _genderOptions),
_buildTextField(_mobileController, l10n.mobileNumber,
keyboardType: TextInputType.phone),
_buildTextField(_emailController, l10n.emailId, _buildTextField(_emailController, l10n.emailId,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress),
readOnly: _isFetched('emailid')), _buildTextField(_aadhaarController, l10n.aadhaarNo,
keyboardType: TextInputType.number),
_buildTextField(_pincodeController, l10n.pincode,
keyboardType: TextInputType.number),
_buildDropdownField( _buildDropdownField(
_marriedController, l10n.marriedYesNo, _yesNoOptions, _marriedController, l10n.marriedYesNo, _yesNoOptions,
mandatory: true), mandatory: true),
],
),
),
),
const SizedBox(height: 16),
// Tile 2: Nominee Details
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.nomineeDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
Text("Nominee 1", style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary)),
const SizedBox(height: 8),
_buildTextField(_nomineeNameController, l10n.nomineeName, _buildTextField(_nomineeNameController, l10n.nomineeName,
mandatory: true), mandatory: true),
_buildTextField(_nomineeRelationController, l10n.relationWithSubscriber,
mandatory: true),
_buildDropdownField(_nomineeMinorController, _buildDropdownField(_nomineeMinorController,
l10n.nomineeMinor, _yesNoOptions, l10n.nomineeMinor, _yesNoOptions, mandatory: true,
mandatory: true, onChanged: (val) { onChanged: (val) {
setState(() { setState(() {
_nomineeMinorController.text = val ?? 'N'; _nomineeMinorController.text = val ?? '';
}); });
}), }),
if (_nomineeMinorController.text == 'Y') ...[ if (_nomineeMinorController.text == 'Y') ...[
_buildTextField(_nomineeDobController, l10n.nomineeDob, _buildTextField(_nomineeDobController, l10n.nomineeDob,
mandatory: true), mandatory: true, onTap: () => _selectDate(context, _nomineeDobController)),
_buildTextField( _buildTextField(
_guardianNameController, l10n.guardianName, _guardianNameController, l10n.guardianName,
mandatory: true), mandatory: true),
], ],
const Divider(height: 32),
Text("Nominee 2", style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary)),
const SizedBox(height: 8),
_buildTextField(_secondNomineeNameController, l10n.secondNomineeName),
_buildTextField(_secondNomineeRelationController, l10n.secondNomineeRelationship),
_buildDropdownField(_secondNomineeMinorController,
l10n.secondNomineeMinor, _yesNoOptions,
onChanged: (val) {
setState(() {
_secondNomineeMinorController.text = val ?? '';
});
}),
],
),
),
),
const SizedBox(height: 16),
// Tile 3: Scheme & APY Details
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.schemeDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildDropdownField(_otherSchemeController, _buildDropdownField(_otherSchemeController,
l10n.isBeneficiaryOtherScheme, _yesNoOptions, l10n.isBeneficiaryOtherScheme, _yesNoOptions,
mandatory: true), mandatory: true),
@@ -242,40 +435,78 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
_buildDropdownField(_collectionChannelController, _buildDropdownField(_collectionChannelController,
l10n.collectionChannel, _collectionChannelOptions, l10n.collectionChannel, _collectionChannelOptions,
mandatory: true), mandatory: true),
_buildDropdownField( _buildTextField(_modeOfCollectionController, l10n.modeOfCollection),
_fatcaController, l10n.fatcaApplicable, _yesNoOptions), ],
),
),
),
const SizedBox(height: 16),
// Tile 4: FATCA / CRS Details (KYC Details)
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.kycdetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildDropdownField(_fatcaController,
l10n.fatcaApplicable, _yesNoOptions),
_buildTextField( _buildTextField(
_birthCountryController, l10n.countryOfBirth), _birthCountryController, l10n.countryOfBirth),
_buildTextField( _buildTextField(_citizenshipCountryController,
_citizenshipCountryController, l10n.countryOfCitizenship), l10n.countryOfCitizenship),
_buildTextField(_taxResidenceCountryController, _buildTextField(_taxResidenceCountryController,
l10n.countryOfTaxResidence), l10n.countryOfTaxResidence),
_buildDropdownField( _buildDropdownField(_usPersonController,
_usPersonController, l10n.usPersonFlag, _yesNoOptions), l10n.usPersonFlag, _yesNoOptions),
const Divider(height: 32), _buildTextField(_fatcaCountController, "FATCA Declaration Count"),
_buildTextField(_docCitizenshipFlagController, "Doc Evidencing Citizenship Flag"),
_buildTextField(_reasonNoEvidenceController, "Reason for No Evidence"),
_buildTextField(_docNameEvidenceController, "Doc Name for Citizenship Evidence"),
],
),
),
),
const SizedBox(height: 16),
// Tile 5: Pension & Contribution Settings
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.contributionAmount,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildDropdownField(_pensionAmountController, _buildDropdownField(_pensionAmountController,
l10n.pensionAmount, _pensionOptions, l10n.pensionAmount, _pensionOptions, mandatory: true,
mandatory: true, onChanged: (val) { onChanged: (val) {
setState(() { setState(() {
_pensionAmountController.text = val ?? '1000'; _pensionAmountController.text = val ?? '';
}); });
}), }),
_buildDropdownField(_contributionTypeController, _buildDropdownField(_contributionTypeController,
l10n.periodicity, _getPeriodicityOptions(l10n), l10n.periodicity, _getPeriodicityOptions(l10n),
mandatory: true, onChanged: (val) { mandatory: true, onChanged: (val) {
setState(() { setState(() {
_contributionTypeController.text = val ?? 'C'; _contributionTypeController.text = val ?? '';
}); });
}), }),
_buildTextField( _buildTextField(
_debitDateController, l10n.subsequentDebitDate, _debitDateController, l10n.subsequentDebitDate,
mandatory: true), mandatory: true, onTap: () => _selectDate(context, _debitDateController)),
], ],
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// Tile 2: Contribution Amount // Tile 6: Contribution Amount Summary
Card( Card(
elevation: 2, elevation: 2,
color: Theme.of(context).colorScheme.secondaryContainer, color: Theme.of(context).colorScheme.secondaryContainer,
@@ -306,8 +537,10 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
ElevatedButton( ElevatedButton(
onPressed: _handleRegister, onPressed: _handleRegister,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primaryContainer, backgroundColor:
foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer, Theme.of(context).colorScheme.primaryContainer,
foregroundColor:
Theme.of(context).colorScheme.onPrimaryContainer,
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
elevation: 4, elevation: 4,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@@ -316,7 +549,8 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
), ),
child: Text( child: Text(
l10n.register, l10n.register,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
@@ -327,9 +561,11 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
); );
} }
Widget _buildDropdownField( Widget _buildDropdownField(TextEditingController controller, String label,
TextEditingController controller, String label, Map<String, String> options, Map<String, String> options,
{bool readOnly = false, bool mandatory = false, void Function(String?)? onChanged}) { {bool readOnly = false,
bool mandatory = false,
void Function(String?)? onChanged}) {
String? currentValue = String? currentValue =
options.containsKey(controller.text) ? controller.text : null; options.containsKey(controller.text) ? controller.text : null;
@@ -337,15 +573,18 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: currentValue, value: currentValue,
onChanged: readOnly ? null : (newValue) { onChanged: readOnly
if (onChanged != null) { ? null
onChanged(newValue); : (newValue) {
} else { if (newValue != null) {
setState(() { setState(() {
controller.text = newValue ?? ''; controller.text = newValue;
}); });
} }
}, if (onChanged != null) {
onChanged(newValue);
}
},
decoration: InputDecoration( decoration: InputDecoration(
labelText: mandatory ? '$label *' : label, labelText: mandatory ? '$label *' : label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
@@ -371,15 +610,18 @@ class _APYRegisterScreenState extends State<APYRegisterScreen> {
Widget _buildTextField(TextEditingController controller, String label, Widget _buildTextField(TextEditingController controller, String label,
{TextInputType keyboardType = TextInputType.text, {TextInputType keyboardType = TextInputType.text,
bool readOnly = false, bool readOnly = false,
bool mandatory = false}) { bool mandatory = false,
VoidCallback? onTap}) {
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: TextFormField( child: TextFormField(
controller: controller, controller: controller,
readOnly: readOnly, readOnly: readOnly || onTap != null,
onTap: onTap,
decoration: InputDecoration( decoration: InputDecoration(
labelText: mandatory ? '$label *' : label, labelText: mandatory ? '$label *' : label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
suffixIcon: onTap != null ? const Icon(Icons.calendar_today) : null,
contentPadding: contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12), const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
), ),

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:kmobile/api/services/yojna_service.dart';
import 'package:kmobile/data/models/user.dart'; import 'package:kmobile/data/models/user.dart';
import 'package:kmobile/di/injection.dart';
import 'package:kmobile/features/yojna/screens/apy_register_screen.dart'; import 'package:kmobile/features/yojna/screens/apy_register_screen.dart';
import 'package:kmobile/l10n/app_localizations.dart'; import 'package:kmobile/l10n/app_localizations.dart';
@@ -20,6 +22,7 @@ class _APYScreenState extends State<APYScreen> {
User? _selectedAccount; User? _selectedAccount;
List<User> _filteredUsers = []; List<User> _filteredUsers = [];
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
bool _isLoading = false;
@override @override
void initState() { void initState() {
@@ -27,7 +30,7 @@ class _APYScreenState extends State<APYScreen> {
_filteredUsers = widget.users _filteredUsers = widget.users
.where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType)) .where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType))
.toList(); .toList();
// Pre-fill the account number if possible // Pre-fill the account number if possible
if (widget.users.isNotEmpty && widget.selectedIndex < widget.users.length) { if (widget.users.isNotEmpty && widget.selectedIndex < widget.users.length) {
if (_filteredUsers.isNotEmpty) { if (_filteredUsers.isNotEmpty) {
@@ -111,58 +114,51 @@ class _APYScreenState extends State<APYScreen> {
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: _isLoading
if (_formKey.currentState!.validate()) { ? null
final mockData = { : () async {
"accountno": _selectedAccount?.accountNo ?? "50069506061", if (_formKey.currentState!.validate()) {
"customerfirstname": "TAMANA", setState(() {
"customermiddlename": "", _isLoading = true;
"customerlastname": "", });
"availablebalance": "634000",
"customerdob": "06061998",
"emailid": "",
"gender": "F",
"married": "Y",
"nomineename": "shubham Kada",
"relationwithsubscriber": "S",
"mobilenumber": "",
"nomineeminor": "N",
"customerno": "30028309887",
"beneficaryofothersociatysecurityschemes": "N",
"whetherincometaxpayer": "N",
"customertitle": "02",
"aadharno": "",
"nameofspouse": "shubham kada",
"ageofjoining": "27",
"pensionamtoptedfor": "1000",
"montlycontributioncalculate": "90",
"collectionchannel": "1",
"subsequentContributionDebitDate": "02012026",
"secondnomineeminor": "N",
"secondnomineename": "shubham kad",
"secondrelationshipwithsubscriber": "",
"pincode": "176215",
"fatcacrsapplicable": "N",
"countryofbirth": "India",
"countryofcitizenship": "India",
"countryofresidencefortaxpurpose": "India",
"uspersonflag": "N",
"fatcadeclarationcount": "",
"documentevidencingcitizenshipflag": "",
"reasonfornoevidence": "",
"nameofdocumentforcitizenshipevidence": "",
"modeofcollection": "Transfer Voucher",
"contributionType": "C"
};
Navigator.push( try {
context, final response = await getIt<YojnaService>()
MaterialPageRoute( .fetchpapydetails(
builder: (context) => APYRegisterScreen(initialData: mockData), accountno: _selectedAccount!.accountNo ?? '');
),
); if (mounted) {
} if (response != null) {
}, Navigator.push(
context,
MaterialPageRoute(
builder: (context) => APYRegisterScreen(
initialData: response),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
"Failed to fetch details. Please try again.")),
);
}
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Error: ${e.toString()}")),
);
}
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
},
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor:
Theme.of(context).colorScheme.primaryContainer, Theme.of(context).colorScheme.primaryContainer,
@@ -174,11 +170,19 @@ class _APYScreenState extends State<APYScreen> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
child: Text( child: _isLoading
l10n.proceedButton, ? const SizedBox(
style: const TextStyle( height: 20,
fontSize: 16, fontWeight: FontWeight.bold), width: 20,
), child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: Text(
l10n.proceedButton,
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
), ),
], ],
), ),
@@ -187,3 +191,4 @@ class _APYScreenState extends State<APYScreen> {
); );
} }
} }

View File

@@ -64,7 +64,7 @@ class _GovSchemeScreenState extends State<GovSchemeScreen> {
selectedIndex: widget.selectedIndex, selectedIndex: widget.selectedIndex,
), ),
), ),
);// Action for APY will be added later ); // Action for APY will be added later
}, },
), ),
), ),

View File

@@ -27,9 +27,9 @@ class _PMMainScreenState extends State<PMMainScreen> {
String? _selectedScheme; String? _selectedScheme;
List<String> _getSchemes(AppLocalizations l10n) => [ List<String> _getSchemes(AppLocalizations l10n) => [
l10n.pmjjbyFull, l10n.pmjjbyFull,
l10n.pmsbyFull, l10n.pmsbyFull,
]; ];
@override @override
void initState() { void initState() {
@@ -76,7 +76,8 @@ class _PMMainScreenState extends State<PMMainScreen> {
return; return;
} }
final String schemeCode = (_selectedScheme == l10n.pmjjbyFull) ? '02' : '01'; final String schemeCode =
(_selectedScheme == l10n.pmjjbyFull) ? '02' : '01';
// Show loading // Show loading
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
@@ -103,7 +104,9 @@ class _PMMainScreenState extends State<PMMainScreen> {
Map<String, dynamic>? data; Map<String, dynamic>? data;
if (response is Map<String, dynamic>) { if (response is Map<String, dynamic>) {
data = response; data = response;
} else if (response is List && response.isNotEmpty && response[0] is Map<String, dynamic>) { } else if (response is List &&
response.isNotEmpty &&
response[0] is Map<String, dynamic>) {
data = response[0] as Map<String, dynamic>; data = response[0] as Map<String, dynamic>;
} }
@@ -169,15 +172,15 @@ class _PMMainScreenState extends State<PMMainScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context); final l10n = AppLocalizations.of(context);
final schemes = _getSchemes(l10n); final schemes = _getSchemes(l10n);
// Ensure _selectedScheme is valid if it was set in a different language // Ensure _selectedScheme is valid if it was set in a different language
if (_selectedScheme != null && !schemes.contains(_selectedScheme)) { if (_selectedScheme != null && !schemes.contains(_selectedScheme)) {
// Try to find the corresponding scheme in the new language // Try to find the corresponding scheme in the new language
// This is a bit tricky, but since we only have two: // This is a bit tricky, but since we only have two:
// If it doesn't match, it might be from the other language. // If it doesn't match, it might be from the other language.
// For simplicity, we can just reset it or try to guess. // For simplicity, we can just reset it or try to guess.
// Better to use non-localized values for the state, but let's just reset for now if it doesn't match // Better to use non-localized values for the state, but let's just reset for now if it doesn't match
_selectedScheme = null; _selectedScheme = null;
} }
return Scaffold( return Scaffold(
@@ -243,23 +246,23 @@ class _PMMainScreenState extends State<PMMainScreen> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: l10n.selectScheme, labelText: l10n.selectScheme,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
contentPadding: contentPadding: const EdgeInsets.symmetric(
const EdgeInsets.symmetric(vertical: 12, horizontal: 12), vertical: 12, horizontal: 12),
), ),
selectedItemBuilder: (BuildContext context) { selectedItemBuilder: (BuildContext context) {
return schemes.map((String scheme) { return schemes.map((String scheme) {
return Container( return Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
scheme, scheme,
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
softWrap: true, softWrap: true,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
), ),
); );
}).toList(); }).toList();
}, },
items: schemes.map((String scheme) { items: schemes.map((String scheme) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: scheme, value: scheme,
@@ -268,7 +271,6 @@ class _PMMainScreenState extends State<PMMainScreen> {
child: Text( child: Text(
scheme, scheme,
style: const TextStyle(fontSize: 15), style: const TextStyle(fontSize: 15),
softWrap: true, softWrap: true,
), ),
), ),
@@ -336,4 +338,3 @@ class _PMMainScreenState extends State<PMMainScreen> {
); );
} }
} }

View File

@@ -119,7 +119,8 @@ class _PMJJBYEnquiryScreenState extends State<PMJJBYEnquiryScreen> {
labelText: l10n.selectFinancialYear, labelText: l10n.selectFinancialYear,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.calendar_today), prefixIcon: const Icon(Icons.calendar_today),
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), contentPadding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
), ),
items: _financialYears.map((String year) { items: _financialYears.map((String year) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
@@ -153,7 +154,9 @@ class _PMJJBYEnquiryScreenState extends State<PMJJBYEnquiryScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text( child: Text(
_errorMessage!, _errorMessage!,
style: TextStyle(color: Colors.red.shade700, fontWeight: FontWeight.bold), style: TextStyle(
color: Colors.red.shade700,
fontWeight: FontWeight.bold),
//textAlign: Center, //textAlign: Center,
), ),
), ),
@@ -177,13 +180,20 @@ class _PMJJBYEnquiryScreenState extends State<PMJJBYEnquiryScreen> {
), ),
), ),
const Divider(), const Divider(),
_buildDetailRow(l10n.customerName, _enquiryData!['customername']), _buildDetailRow(
_buildDetailRow(l10n.policyNumber, _enquiryData!['policynumber']), l10n.customerName, _enquiryData!['customername']),
_buildDetailRow(l10n.accountNumber, _enquiryData!['accountno']), _buildDetailRow(
_buildDetailRow(l10n.premiumAmount, _enquiryData!['preimiumamount']), l10n.policyNumber, _enquiryData!['policynumber']),
_buildDetailRow(l10n.nomineeName, _enquiryData!['nomineename']), _buildDetailRow(
_buildDetailRow(l10n.date, _enquiryData!['transactiondate']), l10n.accountNumber, _enquiryData!['accountno']),
_buildDetailRow(l10n.journalNo, _enquiryData!['journalno']), _buildDetailRow(
l10n.premiumAmount, _enquiryData!['preimiumamount']),
_buildDetailRow(
l10n.nomineeName, _enquiryData!['nomineename']),
_buildDetailRow(
l10n.date, _enquiryData!['transactiondate']),
_buildDetailRow(
l10n.journalNo, _enquiryData!['journalno']),
], ],
), ),
), ),
@@ -202,7 +212,8 @@ class _PMJJBYEnquiryScreenState extends State<PMJJBYEnquiryScreen> {
children: [ children: [
Text( Text(
label, label,
style: const TextStyle(fontWeight: FontWeight.w500, color: Colors.grey), style: const TextStyle(
fontWeight: FontWeight.w500, color: Colors.grey),
), ),
Flexible( Flexible(
child: Text( child: Text(

View File

@@ -15,26 +15,45 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
// Controllers for all requested fields // Controllers for all requested fields
late final _aadhaarController = TextEditingController(text: widget.initialData?['aadharno']?.toString()); late final _aadhaarController =
late final _accountNoController = TextEditingController(text: widget.initialData?['accountno']?.toString()); TextEditingController(text: widget.initialData?['aadharno']?.toString());
late final _balanceController = TextEditingController(text: widget.initialData?['availablebalance']?.toString()); late final _accountNoController =
late final _countryController = TextEditingController(text: widget.initialData?['country']?.toString() ?? 'IN'); TextEditingController(text: widget.initialData?['accountno']?.toString());
late final _dobController = TextEditingController(text: widget.initialData?['customerdob']?.toString()); late final _balanceController = TextEditingController(
late final _nameController = TextEditingController(text: widget.initialData?['customername']?.toString()); text: widget.initialData?['availablebalance']?.toString());
late final _customerNoController = TextEditingController(text: widget.initialData?['customerno']?.toString()); late final _countryController = TextEditingController(
late final _acctOpeningDateController = TextEditingController(text: widget.initialData?['dateofacctopening']?.toString()); text: widget.initialData?['country']?.toString() ?? 'IN');
late final _emailController = TextEditingController(text: widget.initialData?['emailid']?.toString()); late final _dobController = TextEditingController(
late final _financialYearController = TextEditingController(text: widget.initialData?['financialyear']?.toString()); text: widget.initialData?['customerdob']?.toString());
late final _genderController = TextEditingController(text: widget.initialData?['gender']?.toString()); late final _nameController = TextEditingController(
late final _ifscController = TextEditingController(text: widget.initialData?['ifsccode']?.toString()); text: widget.initialData?['customername']?.toString());
late final _marriedController = TextEditingController(text: widget.initialData?['married']?.toString()); late final _customerNoController = TextEditingController(
late final _mobileController = TextEditingController(text: widget.initialData?['mobileno']?.toString()); text: widget.initialData?['customerno']?.toString());
late final _panController = TextEditingController(text: widget.initialData?['pan']?.toString()); late final _acctOpeningDateController = TextEditingController(
late final _pincodeController = TextEditingController(text: widget.initialData?['pincode']?.toString()); text: widget.initialData?['dateofacctopening']?.toString());
late final _policyNumberController = TextEditingController(text: widget.initialData?['policynumber']?.toString()); late final _emailController =
late final _premiumAmountController = TextEditingController(text: widget.initialData?['premiumamount']?.toString()); TextEditingController(text: widget.initialData?['emailid']?.toString());
late final _stateController = TextEditingController(text: widget.initialData?['state']?.toString()); late final _financialYearController = TextEditingController(
text: widget.initialData?['financialyear']?.toString());
late final _genderController =
TextEditingController(text: widget.initialData?['gender']?.toString());
late final _ifscController =
TextEditingController(text: widget.initialData?['ifsccode']?.toString());
late final _marriedController =
TextEditingController(text: widget.initialData?['married']?.toString());
late final _mobileController =
TextEditingController(text: widget.initialData?['mobileno']?.toString());
late final _panController =
TextEditingController(text: widget.initialData?['pan']?.toString());
late final _pincodeController =
TextEditingController(text: widget.initialData?['pincode']?.toString());
late final _policyNumberController = TextEditingController(
text: widget.initialData?['policynumber']?.toString());
late final _premiumAmountController = TextEditingController(
text: widget.initialData?['premiumamount']?.toString());
late final _stateController =
TextEditingController(text: widget.initialData?['state']?.toString());
// Mapping options // Mapping options
final Map<String, String> _healthStatusOptions = { final Map<String, String> _healthStatusOptions = {
'1': 'Excellent', '1': 'Excellent',
@@ -90,16 +109,20 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
// Initialize dropdown controllers if data exists in initialData // Initialize dropdown controllers if data exists in initialData
if (widget.initialData != null) { if (widget.initialData != null) {
if (widget.initialData!.containsKey('ruralcategory')) { if (widget.initialData!.containsKey('ruralcategory')) {
_ruralCategoryController.text = widget.initialData!['ruralcategory'].toString(); _ruralCategoryController.text =
widget.initialData!['ruralcategory'].toString();
} }
if (widget.initialData!.containsKey('healthstatus')) { if (widget.initialData!.containsKey('healthstatus')) {
_healthStatusController.text = widget.initialData!['healthstatus'].toString(); _healthStatusController.text =
widget.initialData!['healthstatus'].toString();
} }
if (widget.initialData!.containsKey('nomineerelationship')) { if (widget.initialData!.containsKey('nomineerelationship')) {
_nomineeRelationshipController.text = widget.initialData!['nomineerelationship'].toString(); _nomineeRelationshipController.text =
widget.initialData!['nomineerelationship'].toString();
} }
if (widget.initialData!.containsKey('nomineeminor')) { if (widget.initialData!.containsKey('nomineeminor')) {
_nomineeMinorController.text = widget.initialData!['nomineeminor'].toString(); _nomineeMinorController.text =
widget.initialData!['nomineeminor'].toString();
} }
} }
} }
@@ -136,9 +159,9 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
} }
bool _isFetched(String key) { bool _isFetched(String key) {
return widget.initialData != null && return widget.initialData != null &&
widget.initialData!.containsKey(key) && widget.initialData!.containsKey(key) &&
widget.initialData![key]?.toString().isNotEmpty == true; widget.initialData![key]?.toString().isNotEmpty == true;
} }
Future<void> _handleRegister() async { Future<void> _handleRegister() async {
@@ -180,8 +203,8 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
ruralcategory: _ruralCategoryController.text, ruralcategory: _ruralCategoryController.text,
); );
String x = response.toString(); String x = response.toString();
if(x.contains('RECORD ALREADY EXISTS')){ if (x.contains('RECORD ALREADY EXISTS')) {
x= l10n.recordAlreadyExists; x = l10n.recordAlreadyExists;
} }
if (mounted) { if (mounted) {
@@ -229,38 +252,77 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
_buildTextField(_nameController, l10n.customerName, readOnly: _isFetched('customername')), _buildTextField(_nameController, l10n.customerName,
_buildTextField(_customerNoController, l10n.customerNo, readOnly: _isFetched('customerno')), readOnly: _isFetched('customername')),
_buildTextField(_accountNoController, l10n.accountNumber, keyboardType: TextInputType.number, readOnly: _isFetched('accountno')), _buildTextField(_customerNoController, l10n.customerNo,
_buildTextField(_balanceController, l10n.availableBalance, keyboardType: TextInputType.number, readOnly: _isFetched('availablebalance')), readOnly: _isFetched('customerno')),
_buildTextField(_aadhaarController, l10n.aadhaarNo, keyboardType: TextInputType.number, readOnly: _isFetched('aadharno')), _buildTextField(_accountNoController, l10n.accountNumber,
_buildTextField(_dobController, l10n.customerDobFormat, readOnly: _isFetched('customerdob')), keyboardType: TextInputType.number,
_buildTextField(_genderController, l10n.gender, readOnly: _isFetched('gender')), readOnly: _isFetched('accountno')),
_buildTextField(_marriedController, l10n.marriedYesNo, readOnly: _isFetched('married')), _buildTextField(_balanceController, l10n.availableBalance,
_buildTextField(_mobileController, l10n.mobileNumber, keyboardType: TextInputType.phone, readOnly: _isFetched('mobileno')), keyboardType: TextInputType.number,
_buildTextField(_emailController, 'Email ID', keyboardType: TextInputType.emailAddress, readOnly: _isFetched('emailid')), readOnly: _isFetched('availablebalance')),
_buildTextField(_panController, l10n.pan, readOnly: _isFetched('pan')), _buildTextField(_aadhaarController, l10n.aadhaarNo,
_buildTextField(_ifscController, l10n.ifscCode, readOnly: _isFetched('ifsccode')), keyboardType: TextInputType.number,
_buildTextField(_acctOpeningDateController, l10n.dateOfAcctOpening, readOnly: _isFetched('dateofacctopening')), readOnly: _isFetched('aadharno')),
_buildTextField(_pincodeController, l10n.pincode, keyboardType: TextInputType.number, readOnly: _isFetched('pincode')), _buildTextField(_dobController, l10n.customerDobFormat,
_buildTextField(_stateController, l10n.state, readOnly: _isFetched('state')), readOnly: _isFetched('customerdob')),
_buildTextField(_countryController, l10n.country, readOnly: _isFetched('country')), _buildTextField(_genderController, l10n.gender,
_buildDropdownField(_ruralCategoryController, l10n.ruralCategory, _ruralOptions, readOnly: _isFetched('ruralcategory')), readOnly: _isFetched('gender')),
_buildTextField(_marriedController, l10n.marriedYesNo,
readOnly: _isFetched('married')),
_buildTextField(_mobileController, l10n.mobileNumber,
keyboardType: TextInputType.phone,
readOnly: _isFetched('mobileno')),
_buildTextField(_emailController, 'Email ID',
keyboardType: TextInputType.emailAddress,
readOnly: _isFetched('emailid')),
_buildTextField(_panController, l10n.pan,
readOnly: _isFetched('pan')),
_buildTextField(_ifscController, l10n.ifscCode,
readOnly: _isFetched('ifsccode')),
_buildTextField(
_acctOpeningDateController, l10n.dateOfAcctOpening,
readOnly: _isFetched('dateofacctopening')),
_buildTextField(_pincodeController, l10n.pincode,
keyboardType: TextInputType.number,
readOnly: _isFetched('pincode')),
_buildTextField(_stateController, l10n.state,
readOnly: _isFetched('state')),
_buildTextField(_countryController, l10n.country,
readOnly: _isFetched('country')),
_buildDropdownField(
_ruralCategoryController, l10n.ruralCategory, _ruralOptions,
readOnly: _isFetched('ruralcategory')),
const Divider(height: 32), const Divider(height: 32),
Text(l10n.policyDetails, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), Text(l10n.policyDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildTextField(_policyNumberController, l10n.policyNumber, readOnly: _isFetched('policynumber')), _buildTextField(_policyNumberController, l10n.policyNumber,
_buildTextField(_premiumAmountController, l10n.premiumAmount, keyboardType: TextInputType.number, readOnly: _isFetched('premiumamount')), readOnly: _isFetched('policynumber')),
_buildTextField(_financialYearController, l10n.financialYear, readOnly: _isFetched('financialyear')), _buildTextField(_premiumAmountController, l10n.premiumAmount,
_buildDropdownField(_healthStatusController, l10n.healthStatus, _healthStatusOptions), keyboardType: TextInputType.number,
_buildTextField(_collectionChannelController, l10n.collectionChannel), readOnly: _isFetched('premiumamount')),
_buildTextField(_financialYearController, l10n.financialYear,
readOnly: _isFetched('financialyear')),
_buildDropdownField(_healthStatusController, l10n.healthStatus,
_healthStatusOptions),
_buildTextField(
_collectionChannelController, l10n.collectionChannel),
const Divider(height: 32), const Divider(height: 32),
Text(l10n.nomineeDetails, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), Text(l10n.nomineeDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildTextField(_nomineeNameController, l10n.nomineeName), _buildTextField(_nomineeNameController, l10n.nomineeName),
_buildTextField(_nomineeAddressController, l10n.nomineeAddress), _buildTextField(_nomineeAddressController, l10n.nomineeAddress),
_buildDropdownField(_nomineeRelationshipController, l10n.nomineeRelationship, _relationshipOptions, readOnly: _isFetched('nomineerelationship')), _buildDropdownField(_nomineeRelationshipController,
_buildDropdownField(_nomineeMinorController, l10n.nomineeMinor, _minorOptions, readOnly: _isFetched('nomineeminor')), l10n.nomineeRelationship, _relationshipOptions,
readOnly: _isFetched('nomineerelationship')),
_buildDropdownField(
_nomineeMinorController, l10n.nomineeMinor, _minorOptions,
readOnly: _isFetched('nomineeminor')),
const SizedBox(height: 24), const SizedBox(height: 24),
ElevatedButton( ElevatedButton(
onPressed: _handleRegister, onPressed: _handleRegister,
@@ -274,7 +336,8 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
), ),
child: Text( child: Text(
l10n.register, l10n.register,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
@@ -285,25 +348,29 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
); );
} }
Widget _buildDropdownField( Widget _buildDropdownField(TextEditingController controller, String label,
TextEditingController controller, String label, Map<String, String> options, Map<String, String> options,
{bool readOnly = false}) { {bool readOnly = false}) {
// Determine current value // Determine current value
String? currentValue = options.containsKey(controller.text) ? controller.text : null; String? currentValue =
options.containsKey(controller.text) ? controller.text : null;
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: currentValue, value: currentValue,
onChanged: readOnly ? null : (newValue) { onChanged: readOnly
setState(() { ? null
controller.text = newValue ?? ''; : (newValue) {
}); setState(() {
}, controller.text = newValue ?? '';
});
},
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
), ),
items: options.entries.map((entry) { items: options.entries.map((entry) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
@@ -315,7 +382,9 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
); );
} }
Widget _buildTextField(TextEditingController controller, String label, {TextInputType keyboardType = TextInputType.text, bool readOnly = false}) { Widget _buildTextField(TextEditingController controller, String label,
{TextInputType keyboardType = TextInputType.text,
bool readOnly = false}) {
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: TextFormField( child: TextFormField(
@@ -324,7 +393,8 @@ class _PMJJBYScreenState extends State<PMJJBYScreen> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
), ),
keyboardType: keyboardType, keyboardType: keyboardType,
), ),

View File

@@ -119,7 +119,8 @@ class _PMSBYEnquiryScreenState extends State<PMSBYEnquiryScreen> {
labelText: l10n.selectFinancialYear, labelText: l10n.selectFinancialYear,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
prefixIcon: const Icon(Icons.calendar_today), prefixIcon: const Icon(Icons.calendar_today),
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), contentPadding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
), ),
items: _financialYears.map((String year) { items: _financialYears.map((String year) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
@@ -153,7 +154,9 @@ class _PMSBYEnquiryScreenState extends State<PMSBYEnquiryScreen> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text( child: Text(
_errorMessage!, _errorMessage!,
style: TextStyle(color: Colors.red.shade700, fontWeight: FontWeight.bold), style: TextStyle(
color: Colors.red.shade700,
fontWeight: FontWeight.bold),
//textAlign: Center, //textAlign: Center,
), ),
), ),
@@ -177,13 +180,24 @@ class _PMSBYEnquiryScreenState extends State<PMSBYEnquiryScreen> {
), ),
), ),
const Divider(), const Divider(),
_buildDetailRow(l10n.customerName, _enquiryData!['customername']), _buildDetailRow(
_buildDetailRow(l10n.policyNumber, _enquiryData!['policynumber'] ?? _enquiryData!['policyno']), l10n.customerName, _enquiryData!['customername']),
_buildDetailRow(l10n.accountNumber, _enquiryData!['accountno']), _buildDetailRow(
_buildDetailRow(l10n.premiumAmount, _enquiryData!['preimiumamount'] ?? _enquiryData!['premiumamount']), l10n.policyNumber,
_buildDetailRow(l10n.nomineeName, _enquiryData!['nomineename']), _enquiryData!['policynumber'] ??
_buildDetailRow(l10n.date, _enquiryData!['transactiondate']), _enquiryData!['policyno']),
_buildDetailRow(l10n.journalNo, _enquiryData!['journalno']), _buildDetailRow(
l10n.accountNumber, _enquiryData!['accountno']),
_buildDetailRow(
l10n.premiumAmount,
_enquiryData!['preimiumamount'] ??
_enquiryData!['premiumamount']),
_buildDetailRow(
l10n.nomineeName, _enquiryData!['nomineename']),
_buildDetailRow(
l10n.date, _enquiryData!['transactiondate']),
_buildDetailRow(
l10n.journalNo, _enquiryData!['journalno']),
], ],
), ),
), ),
@@ -202,7 +216,8 @@ class _PMSBYEnquiryScreenState extends State<PMSBYEnquiryScreen> {
children: [ children: [
Text( Text(
label, label,
style: const TextStyle(fontWeight: FontWeight.w500, color: Colors.grey), style: const TextStyle(
fontWeight: FontWeight.w500, color: Colors.grey),
), ),
Flexible( Flexible(
child: Text( child: Text(

View File

@@ -15,30 +15,54 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
// Controllers for all requested fields // Controllers for all requested fields
late final _aadhaarController = TextEditingController(text: widget.initialData?['aadharno']?.toString()); late final _aadhaarController =
late final _accountNoController = TextEditingController(text: widget.initialData?['accountno']?.toString()); TextEditingController(text: widget.initialData?['aadharno']?.toString());
late final _balanceController = TextEditingController(text: widget.initialData?['availablebalance']?.toString()); late final _accountNoController =
late final _countryController = TextEditingController(text: widget.initialData?['country']?.toString() ?? 'IN'); TextEditingController(text: widget.initialData?['accountno']?.toString());
late final _dobController = TextEditingController(text: widget.initialData?['customerdob']?.toString()); late final _balanceController = TextEditingController(
late final _nameController = TextEditingController(text: widget.initialData?['customername']?.toString()); text: widget.initialData?['availablebalance']?.toString());
late final _customerNoController = TextEditingController(text: widget.initialData?['customerno']?.toString()); late final _countryController = TextEditingController(
late final _acctOpeningDateController = TextEditingController(text: widget.initialData?['dateofacctopening']?.toString()); text: widget.initialData?['country']?.toString() ?? 'IN');
late final _emailController = TextEditingController(text: widget.initialData?['emailid']?.toString()); late final _dobController = TextEditingController(
late final _financialYearController = TextEditingController(text: widget.initialData?['financialyear']?.toString()); text: widget.initialData?['customerdob']?.toString());
late final _genderController = TextEditingController(text: widget.initialData?['gender']?.toString()); late final _nameController = TextEditingController(
late final _ifscController = TextEditingController(text: widget.initialData?['ifsccode']?.toString()); text: widget.initialData?['customername']?.toString());
late final _marriedController = TextEditingController(text: widget.initialData?['married']?.toString()); late final _customerNoController = TextEditingController(
late final _mobileController = TextEditingController(text: widget.initialData?['mobileno']?.toString()); text: widget.initialData?['customerno']?.toString());
late final _panController = TextEditingController(text: widget.initialData?['pan']?.toString()); late final _acctOpeningDateController = TextEditingController(
late final _pincodeController = TextEditingController(text: widget.initialData?['pincode']?.toString()); text: widget.initialData?['dateofacctopening']?.toString());
late final _policyNumberController = TextEditingController(text: widget.initialData?['policyno']?.toString()); late final _emailController =
late final _premiumAmountController = TextEditingController(text: widget.initialData?['premiumamount']?.toString()); TextEditingController(text: widget.initialData?['emailid']?.toString());
late final _stateController = TextEditingController(text: widget.initialData?['state']?.toString()); late final _financialYearController = TextEditingController(
late final _address1Controller = TextEditingController(text: widget.initialData?['address1']?.toString()); text: widget.initialData?['financialyear']?.toString());
late final _address2Controller = TextEditingController(text: widget.initialData?['address2']?.toString()); late final _genderController =
late final _cityController = TextEditingController(text: widget.initialData?['city']?.toString()); TextEditingController(text: widget.initialData?['gender']?.toString());
late final _relationWithNomineeController = TextEditingController(text: widget.initialData?['relationwithnominee']?.toString()); late final _ifscController =
late final _policyStatusController = TextEditingController(text: widget.initialData?['policystatus']?.toString()); TextEditingController(text: widget.initialData?['ifsccode']?.toString());
late final _marriedController =
TextEditingController(text: widget.initialData?['married']?.toString());
late final _mobileController =
TextEditingController(text: widget.initialData?['mobileno']?.toString());
late final _panController =
TextEditingController(text: widget.initialData?['pan']?.toString());
late final _pincodeController =
TextEditingController(text: widget.initialData?['pincode']?.toString());
late final _policyNumberController =
TextEditingController(text: widget.initialData?['policyno']?.toString());
late final _premiumAmountController = TextEditingController(
text: widget.initialData?['premiumamount']?.toString());
late final _stateController =
TextEditingController(text: widget.initialData?['state']?.toString());
late final _address1Controller =
TextEditingController(text: widget.initialData?['address1']?.toString());
late final _address2Controller =
TextEditingController(text: widget.initialData?['address2']?.toString());
late final _cityController =
TextEditingController(text: widget.initialData?['city']?.toString());
late final _relationWithNomineeController = TextEditingController(
text: widget.initialData?['relationwithnominee']?.toString());
late final _policyStatusController = TextEditingController(
text: widget.initialData?['policystatus']?.toString());
// Mapping options // Mapping options
final Map<String, String> _healthStatusOptions = { final Map<String, String> _healthStatusOptions = {
@@ -95,16 +119,20 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
// Initialize dropdown controllers if data exists in initialData // Initialize dropdown controllers if data exists in initialData
if (widget.initialData != null) { if (widget.initialData != null) {
if (widget.initialData!.containsKey('ruralcategory')) { if (widget.initialData!.containsKey('ruralcategory')) {
_ruralCategoryController.text = widget.initialData!['ruralcategory'].toString(); _ruralCategoryController.text =
widget.initialData!['ruralcategory'].toString();
} }
if (widget.initialData!.containsKey('healthstatus')) { if (widget.initialData!.containsKey('healthstatus')) {
_healthStatusController.text = widget.initialData!['healthstatus'].toString(); _healthStatusController.text =
widget.initialData!['healthstatus'].toString();
} }
if (widget.initialData!.containsKey('relationwithnominee')) { if (widget.initialData!.containsKey('relationwithnominee')) {
_nomineeRelationshipController.text = widget.initialData!['relationwithnominee'].toString(); _nomineeRelationshipController.text =
widget.initialData!['relationwithnominee'].toString();
} }
if (widget.initialData!.containsKey('nomineeminor')) { if (widget.initialData!.containsKey('nomineeminor')) {
_nomineeMinorController.text = widget.initialData!['nomineeminor'].toString(); _nomineeMinorController.text =
widget.initialData!['nomineeminor'].toString();
} }
} }
} }
@@ -146,9 +174,9 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
} }
bool _isFetched(String key) { bool _isFetched(String key) {
return widget.initialData != null && return widget.initialData != null &&
widget.initialData!.containsKey(key) && widget.initialData!.containsKey(key) &&
widget.initialData![key]?.toString().isNotEmpty == true; widget.initialData![key]?.toString().isNotEmpty == true;
} }
Future<void> _handleRegister() async { Future<void> _handleRegister() async {
@@ -192,8 +220,8 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
policystatus: _policyStatusController.text, policystatus: _policyStatusController.text,
); );
String x = response.toString(); String x = response.toString();
if(x.contains('RECORD ALREADY EXISTS')){ if (x.contains('RECORD ALREADY EXISTS')) {
x= l10n.recordAlreadyExists; x = l10n.recordAlreadyExists;
} }
if (mounted) { if (mounted) {
@@ -241,43 +269,87 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
_buildTextField(_nameController, l10n.customerName, readOnly: _isFetched('customername')), _buildTextField(_nameController, l10n.customerName,
_buildTextField(_customerNoController, l10n.customerNo, readOnly: _isFetched('customerno')), readOnly: _isFetched('customername')),
_buildTextField(_accountNoController, l10n.accountNumber, keyboardType: TextInputType.number, readOnly: _isFetched('accountno')), _buildTextField(_customerNoController, l10n.customerNo,
_buildTextField(_balanceController, l10n.availableBalance, keyboardType: TextInputType.number, readOnly: _isFetched('availablebalance')), readOnly: _isFetched('customerno')),
_buildTextField(_aadhaarController, l10n.aadhaarNo, keyboardType: TextInputType.number, readOnly: _isFetched('aadharno')), _buildTextField(_accountNoController, l10n.accountNumber,
_buildTextField(_dobController, l10n.customerDobFormat, readOnly: _isFetched('customerdob')), keyboardType: TextInputType.number,
_buildTextField(_genderController, l10n.gender, readOnly: _isFetched('gender')), readOnly: _isFetched('accountno')),
_buildTextField(_marriedController, l10n.marriedYesNo, readOnly: _isFetched('married')), _buildTextField(_balanceController, l10n.availableBalance,
_buildTextField(_mobileController, l10n.mobileNumber, keyboardType: TextInputType.phone, readOnly: _isFetched('mobileno')), keyboardType: TextInputType.number,
_buildTextField(_emailController, 'Email ID', keyboardType: TextInputType.emailAddress, readOnly: _isFetched('emailid')), readOnly: _isFetched('availablebalance')),
_buildTextField(_address1Controller, l10n.address1, readOnly: _isFetched('address1')), _buildTextField(_aadhaarController, l10n.aadhaarNo,
_buildTextField(_address2Controller, l10n.address2, readOnly: _isFetched('address2')), keyboardType: TextInputType.number,
_buildTextField(_cityController, l10n.city, readOnly: _isFetched('city')), readOnly: _isFetched('aadharno')),
_buildTextField(_panController, l10n.pan, readOnly: _isFetched('pan')), _buildTextField(_dobController, l10n.customerDobFormat,
_buildTextField(_ifscController, l10n.ifscCode, readOnly: _isFetched('ifsccode')), readOnly: _isFetched('customerdob')),
_buildTextField(_acctOpeningDateController, l10n.dateOfAcctOpening, readOnly: _isFetched('dateofacctopening')), _buildTextField(_genderController, l10n.gender,
_buildTextField(_pincodeController, l10n.pincode, keyboardType: TextInputType.number, readOnly: _isFetched('pincode')), readOnly: _isFetched('gender')),
_buildTextField(_stateController, l10n.state, readOnly: _isFetched('state')), _buildTextField(_marriedController, l10n.marriedYesNo,
_buildTextField(_countryController, l10n.country, readOnly: _isFetched('country')), readOnly: _isFetched('married')),
_buildDropdownField(_ruralCategoryController, l10n.ruralCategory, _ruralOptions, readOnly: _isFetched('ruralcategory')), _buildTextField(_mobileController, l10n.mobileNumber,
keyboardType: TextInputType.phone,
readOnly: _isFetched('mobileno')),
_buildTextField(_emailController, 'Email ID',
keyboardType: TextInputType.emailAddress,
readOnly: _isFetched('emailid')),
_buildTextField(_address1Controller, l10n.address1,
readOnly: _isFetched('address1')),
_buildTextField(_address2Controller, l10n.address2,
readOnly: _isFetched('address2')),
_buildTextField(_cityController, l10n.city,
readOnly: _isFetched('city')),
_buildTextField(_panController, l10n.pan,
readOnly: _isFetched('pan')),
_buildTextField(_ifscController, l10n.ifscCode,
readOnly: _isFetched('ifsccode')),
_buildTextField(
_acctOpeningDateController, l10n.dateOfAcctOpening,
readOnly: _isFetched('dateofacctopening')),
_buildTextField(_pincodeController, l10n.pincode,
keyboardType: TextInputType.number,
readOnly: _isFetched('pincode')),
_buildTextField(_stateController, l10n.state,
readOnly: _isFetched('state')),
_buildTextField(_countryController, l10n.country,
readOnly: _isFetched('country')),
_buildDropdownField(
_ruralCategoryController, l10n.ruralCategory, _ruralOptions,
readOnly: _isFetched('ruralcategory')),
const Divider(height: 32), const Divider(height: 32),
Text(l10n.policyDetails, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), Text(l10n.policyDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildTextField(_policyNumberController, l10n.policyNumber, readOnly: _isFetched('policyno')), _buildTextField(_policyNumberController, l10n.policyNumber,
_buildTextField(_premiumAmountController, l10n.premiumAmount, keyboardType: TextInputType.number, readOnly: _isFetched('premiumamount')), readOnly: _isFetched('policyno')),
_buildTextField(_financialYearController, l10n.financialYear, readOnly: _isFetched('financialyear')), _buildTextField(_premiumAmountController, l10n.premiumAmount,
_buildTextField(_policyStatusController, l10n.policyStatus, readOnly: _isFetched('policystatus')), keyboardType: TextInputType.number,
_buildDropdownField(_healthStatusController, l10n.healthStatus, _healthStatusOptions), readOnly: _isFetched('premiumamount')),
_buildTextField(_collectionChannelController, l10n.collectionChannel), _buildTextField(_financialYearController, l10n.financialYear,
readOnly: _isFetched('financialyear')),
_buildTextField(_policyStatusController, l10n.policyStatus,
readOnly: _isFetched('policystatus')),
_buildDropdownField(_healthStatusController, l10n.healthStatus,
_healthStatusOptions),
_buildTextField(
_collectionChannelController, l10n.collectionChannel),
const Divider(height: 32), const Divider(height: 32),
Text(l10n.nomineeDetails, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), Text(l10n.nomineeDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
_buildTextField(_nomineeNameController, l10n.nomineeName), _buildTextField(_nomineeNameController, l10n.nomineeName),
_buildTextField(_nomineeAddressController, l10n.nomineeAddress), _buildTextField(_nomineeAddressController, l10n.nomineeAddress),
_buildDropdownField(_relationWithNomineeController, l10n.relationWithNominee, _relationshipOptions, readOnly: _isFetched('relationwithnominee')), _buildDropdownField(_relationWithNomineeController,
_buildTextField(_nomineeRelationshipController, l10n.nomineeRelationship), l10n.relationWithNominee, _relationshipOptions,
_buildDropdownField(_nomineeMinorController, l10n.nomineeMinor, _minorOptions, readOnly: _isFetched('nomineeminor')), readOnly: _isFetched('relationwithnominee')),
_buildTextField(
_nomineeRelationshipController, l10n.nomineeRelationship),
_buildDropdownField(
_nomineeMinorController, l10n.nomineeMinor, _minorOptions,
readOnly: _isFetched('nomineeminor')),
const SizedBox(height: 24), const SizedBox(height: 24),
ElevatedButton( ElevatedButton(
onPressed: _handleRegister, onPressed: _handleRegister,
@@ -291,7 +363,8 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
), ),
child: Text( child: Text(
l10n.register, l10n.register,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
), ),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
@@ -302,25 +375,29 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
); );
} }
Widget _buildDropdownField( Widget _buildDropdownField(TextEditingController controller, String label,
TextEditingController controller, String label, Map<String, String> options, Map<String, String> options,
{bool readOnly = false}) { {bool readOnly = false}) {
// Determine current value // Determine current value
String? currentValue = options.containsKey(controller.text) ? controller.text : null; String? currentValue =
options.containsKey(controller.text) ? controller.text : null;
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: DropdownButtonFormField<String>( child: DropdownButtonFormField<String>(
value: currentValue, value: currentValue,
onChanged: readOnly ? null : (newValue) { onChanged: readOnly
setState(() { ? null
controller.text = newValue ?? ''; : (newValue) {
}); setState(() {
}, controller.text = newValue ?? '';
});
},
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
), ),
items: options.entries.map((entry) { items: options.entries.map((entry) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
@@ -332,7 +409,9 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
); );
} }
Widget _buildTextField(TextEditingController controller, String label, {TextInputType keyboardType = TextInputType.text, bool readOnly = false}) { Widget _buildTextField(TextEditingController controller, String label,
{TextInputType keyboardType = TextInputType.text,
bool readOnly = false}) {
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 16.0), padding: const EdgeInsets.only(bottom: 16.0),
child: TextFormField( child: TextFormField(
@@ -341,7 +420,8 @@ class _PMSBYScreenState extends State<PMSBYScreen> {
decoration: InputDecoration( decoration: InputDecoration(
labelText: label, labelText: label,
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
), ),
keyboardType: keyboardType, keyboardType: keyboardType,
), ),

View File

@@ -24,4 +24,4 @@ void main() async {
// } // }
await setupDependencies(); await setupDependencies();
runApp(const KMobile()); runApp(const KMobile());
} }

View File

@@ -134,7 +134,8 @@ void main() {
// GROUP 1: Screen Rendering // GROUP 1: Screen Rendering
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
group('Screen Rendering', () { group('Screen Rendering', () {
testWidgets('renders AppBar with "Account Statement" title', (tester) async { testWidgets('renders AppBar with "Account Statement" title',
(tester) async {
await tester.pumpWidget(_buildTestApp(users: [testUser])); await tester.pumpWidget(_buildTestApp(users: [testUser]));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
@@ -204,8 +205,7 @@ void main() {
expect(find.text('1234567890'), findsOneWidget); expect(find.text('1234567890'), findsOneWidget);
}); });
testWidgets('dropdown shows all user accounts when tapped', testWidgets('dropdown shows all user accounts when tapped', (tester) async {
(tester) async {
await tester.pumpWidget(_buildTestApp(users: [testUser, testUser2])); await tester.pumpWidget(_buildTestApp(users: [testUser, testUser2]));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
@@ -370,8 +370,7 @@ void main() {
// Find the Icon for credit transactions (call_received) // Find the Icon for credit transactions (call_received)
final iconFinder = find.byWidgetPredicate( final iconFinder = find.byWidgetPredicate(
(widget) => (widget) => widget is Icon && widget.color == const Color(0xFF10BB10),
widget is Icon && widget.color == const Color(0xFF10BB10),
); );
expect(iconFinder, findsOneWidget); expect(iconFinder, findsOneWidget);
}); });
@@ -388,7 +387,8 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(SnackBar), findsOneWidget); expect(find.byType(SnackBar), findsOneWidget);
expect(find.textContaining('Failed to load transactions'), findsOneWidget); expect(
find.textContaining('Failed to load transactions'), findsOneWidget);
}); });
}); });
@@ -441,8 +441,7 @@ void main() {
// GROUP 9: PDF Export // GROUP 9: PDF Export
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
group('PDF Export', () { group('PDF Export', () {
testWidgets( testWidgets('pressing download FAB with no transactions shows snackbar',
'pressing download FAB with no transactions shows snackbar',
(tester) async { (tester) async {
mockRepo.mockTransactions = []; mockRepo.mockTransactions = [];