Localizations for deposit

This commit is contained in:
2026-03-25 16:05:44 +05:30
parent 4e39cb8493
commit 1f764990d5
5 changed files with 345 additions and 136 deletions

View File

@@ -64,82 +64,112 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
late final _monthlyRDInstallmentDueDayController = TextEditingController();
late final _rdInstlFreqController = TextEditingController();
final Map<String, String> _productOptions = {
'20': 'Term Deposit',
'25': 'Fixed Deposit',
'28': 'Recurring Deposit',
};
Map<String, String> get _productOptions {
final l10n = AppLocalizations.of(context);
return {
'20': l10n.termDepositOption,
'25': l10n.fixedDepositOption,
'28': l10n.recurringDepositOption,
};
}
final Map<String, String> _typeOptions = {
'01': 'Member',
'02': 'Non-Member',
'03': 'Staff',
'04': 'Govt',
'05': 'School',
'06': 'Panchayat',
'07': 'Trusts',
'08': 'Municipal Council',
'09': 'NRO',
'10': 'Bank',
'11': 'No Frill',
'12': 'Special Schemes',
'13': 'Minor',
};
Map<String, String> get _typeOptions {
final l10n = AppLocalizations.of(context);
return {
'01': l10n.memberOption,
'02': l10n.nonMemberOption,
'03': l10n.staffOption,
'04': l10n.govtOption,
'05': l10n.schoolOption,
'06': l10n.panchayatOption,
'07': l10n.trustsOption,
'08': l10n.municipalCouncilOption,
'09': l10n.nroOption,
'10': l10n.bankOption,
'11': l10n.noFrillOption,
'12': l10n.specialSchemesOption,
'13': l10n.minorOption,
};
}
final Map<String, String> _customerCategoryOptions = {
'1': 'Public Individual',
'2': 'Societies',
'3': 'Senior Citizen',
'5': 'Government',
'6': 'Local Bodies',
'7': 'Other',
};
Map<String, String> get _customerCategoryOptions {
final l10n = AppLocalizations.of(context);
return {
'1': l10n.publicIndividualOption,
'2': l10n.societiesOption,
'3': l10n.seniorCitizenOption,
'5': l10n.governmentOption,
'6': l10n.localBodiesOption,
'7': l10n.otherOption,
};
}
final Map<String, String> _termLocationOptions = {
'10': 'SB/CA',
'13': '4690 Days',
'14': '91180 Days',
'15': '180 Days1 Year',
'16': '1 Year<18 Months',
'20': '18 Months<2 Years',
'17': '23 Years',
'18': '310 Years',
'22': 'Above 10 Years',
'24': 'Dev Kanya Yojna 9+1',
'25': 'Hazar Dain Lakh Ley Jayain',
};
Map<String, String> get _termLocationOptions {
final l10n = AppLocalizations.of(context);
return {
'10': l10n.sbCaOption,
'13': l10n.days46_90Option,
'14': l10n.days91_180Option,
'15': l10n.days180_1YearOption,
'16': l10n.year1_18MonthsOption,
'20': l10n.months18_2YearsOption,
'17': l10n.years2_3Option,
'18': l10n.years3_10Option,
'22': l10n.above10YearsOption,
'24': l10n.devKanyaYojnaOption,
'25': l10n.hazarDainLakhOption,
};
}
final Map<String, String> _currencyOptions = {
'1': 'INR',
};
Map<String, String> get _currencyOptions {
final l10n = AppLocalizations.of(context);
return {
'1': l10n.currencyINR,
};
}
final Map<String, String> _acctSgmtCodeOptions = {
'0706': 'Public Individual',
'5002': 'Societies',
'5005': 'Government',
'5050': 'GL Others',
};
Map<String, String> get _acctSgmtCodeOptions {
final l10n = AppLocalizations.of(context);
return {
'0706': l10n.publicIndividualOption,
'5002': l10n.societiesOption,
'5005': l10n.governmentOption,
'5050': l10n.glOthersOption,
};
}
final Map<String, String> _interestPaymentMethodOptions = {
'R': 'Re-invest',
};
Map<String, String> get _interestPaymentMethodOptions {
final l10n = AppLocalizations.of(context);
return {
'R': l10n.reInvestOption,
};
}
final Map<String, String> _termBasisOptions = {
'D': 'Days',
'M': 'Months',
};
Map<String, String> get _termBasisOptions {
final l10n = AppLocalizations.of(context);
return {
'D': l10n.daysOption,
'M': l10n.monthsOption,
};
}
final Map<String, String> _interestFrequencyOptions = {
'M': 'On Maturity / Roll Over',
'1M': 'Monthly',
'3M': 'Quarterly',
'1A': 'Anniversary Monthly',
'3A': 'Anniversary Quarterly',
};
Map<String, String> get _interestFrequencyOptions {
final l10n = AppLocalizations.of(context);
return {
'M': l10n.onMaturityOption,
'1M': l10n.monthlyOption,
'3M': l10n.quarterlyOption,
'1A': l10n.anniversaryMonthlyOption,
'3A': l10n.anniversaryQuarterlyOption,
};
}
final Map<String, String> _rdInstlFreqOptions = {
'M': 'Monthly',
};
Map<String, String> get _rdInstlFreqOptions {
final l10n = AppLocalizations.of(context);
return {
'M': l10n.monthlyOption,
};
}
@override
void dispose() {
@@ -264,46 +294,50 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
if (response != null && response is Map<String, dynamic>) {
if (mounted) {
final l10n = AppLocalizations.of(context);
if (response['error'] == 'INCORRECT_TPIN' || response['message'] == 'INCORRECT_TPIN') {
_showSimpleDialog('Invalid TPIN', 'The TPIN you entered is incorrect. Please try again.');
_showSimpleDialog(l10n.invalidTpin, l10n.incorrectTpinMessage);
} else if (response['status'] == 'FAILED') {
_showFailureDialog(response['message']?.toString());
} else if (response.containsKey('accountno')) {
_showResponseDialog(response);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Unexpected response from server")),
SnackBar(content: Text(l10n.unexpectedResponse)),
);
}
}
} else {
if (mounted) {
final l10n = AppLocalizations.of(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Failed to create deposit")),
SnackBar(content: Text(l10n.failedToCreateDeposit)),
);
}
}
} on DioException catch (e) {
if (mounted) {
final l10n = AppLocalizations.of(context);
try {
final errorBody = e.response?.data;
if (errorBody is Map && (errorBody['error'] == 'INCORRECT_TPIN' || errorBody['message'] == 'INCORRECT_TPIN')) {
_showSimpleDialog('Invalid TPIN', 'The TPIN you entered is incorrect. Please try again.');
_showSimpleDialog(l10n.invalidTpin, l10n.incorrectTpinMessage);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Error: ${e.message}")),
SnackBar(content: Text("${l10n.error}: ${e.message}")),
);
}
} catch (_) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Internal Server Error")),
SnackBar(content: Text(l10n.internalServerError)),
);
}
}
} catch (e) {
if (mounted) {
final l10n = AppLocalizations.of(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Error: $e")),
SnackBar(content: Text("${l10n.error}: $e")),
);
}
} finally {
@@ -316,6 +350,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
}
Future<void> _showSimpleDialog(String title, String message) async {
final l10n = AppLocalizations.of(context);
return showDialog<void>(
context: context,
barrierDismissible: false,
@@ -331,7 +366,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
),
actions: <Widget>[
TextButton(
child: const Text("OK"),
child: Text(l10n.ok),
onPressed: () {
Navigator.of(context).pop();
},
@@ -343,6 +378,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
}
void _showFailureDialog(String? apiMessage) {
final l10n = AppLocalizations.of(context);
showDialog(
context: context,
builder: (context) => AlertDialog(
@@ -350,31 +386,31 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
children: [
Icon(Icons.error_outline, color: Theme.of(context).colorScheme.error),
const SizedBox(width: 8),
const Text("Creation Failed"),
Text(l10n.creationFailed),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Account creation could not be completed at this time.",
style: TextStyle(fontWeight: FontWeight.bold),
Text(
l10n.accountCreationFailed,
style: const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
if (apiMessage != null) ...[
Text("Reason: $apiMessage"),
Text(l10n.reason(apiMessage)),
const SizedBox(height: 12),
],
const Text(
"Please ensure that the provided details (term length, basis, interest frequency, etc.) are correct and compatible with the selected product. If the issue persists, please contact the branch.",
Text(
l10n.creationFailedDescription,
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text("OK"),
child: Text(l10n.ok),
),
],
),
@@ -382,6 +418,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
}
void _showResponseDialog(Map<String, dynamic> response) {
final l10n = AppLocalizations.of(context);
final accountNo = response['accountno']?.toString() ?? 'N/A';
final accountTypeRaw = response['accounttype']?.toString() ?? '';
final accountTypeText = _productOptions[accountTypeRaw] ?? accountTypeRaw;
@@ -391,16 +428,16 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Text("Deposit Created Successfully"),
title: Text(l10n.depositCreatedSuccessfully),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Account No: $accountNo"),
Text("${l10n.accountNumberLabel}: $accountNo"),
const SizedBox(height: 8),
Text("Account Type: $accountTypeText"),
Text("${l10n.accountTypeLabel}: $accountTypeText"),
const SizedBox(height: 8),
Text("Amount: $amount"),
Text(l10n.amountValue(amount)),
],
),
actions: [
@@ -408,7 +445,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
onPressed: () {
Navigator.of(context).popUntil((route) => route.isFirst);
},
child: const Text("OK"),
child: Text(l10n.ok),
),
],
),
@@ -420,7 +457,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
final l10n = AppLocalizations.of(context);
return Scaffold(
appBar: AppBar(
title: const Text("Create Deposit"),
title: Text(l10n.createDeposit),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
@@ -437,19 +474,19 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Customer Information",
style: TextStyle(
Text(l10n.customerInformation,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildTextField(_fromAcctNoController, "From Account No",
_buildTextField(_fromAcctNoController, l10n.fromAccountNo,
mandatory: true, readOnly: true),
_buildTextField(_cifNoController, "CIF No"),
_buildTextField(_idNoController, "ID No"),
_buildTextField(_customerNameController, "Customer Name"),
_buildTextField(_nationalityController, "Nationality"),
_buildTextField(_addressLine1Controller, "Address Line 1"),
_buildTextField(_addressLine2Controller, "Address Line 2"),
_buildTextField(_pincodeController, "Pincode",
_buildTextField(_cifNoController, l10n.cifNo),
_buildTextField(_idNoController, l10n.idNo),
_buildTextField(_customerNameController, l10n.customerName),
_buildTextField(_nationalityController, l10n.nationality),
_buildTextField(_addressLine1Controller, l10n.addressLine1),
_buildTextField(_addressLine2Controller, l10n.addressLine2),
_buildTextField(_pincodeController, l10n.pincodeLabel,
keyboardType: TextInputType.number),
],
),
@@ -464,30 +501,30 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Deposit Details",
style: TextStyle(
Text(l10n.depositDetails,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildDropdownField(
_productController, "Product", _productOptions,
_productController, l10n.product, _productOptions,
mandatory: true, onChanged: (val) {
setState(() {
_productController.text = val ?? '';
});
}),
_buildDropdownField(_typeController, "Type", _typeOptions,
_buildDropdownField(_typeController, l10n.type, _typeOptions,
mandatory: true),
_buildDropdownField(_customerCategoryController,
"Customer Category", _customerCategoryOptions,
l10n.customerCategory, _customerCategoryOptions,
mandatory: true),
_buildDropdownField(_termLocationController,
"Term Location", _termLocationOptions,
l10n.termLocation, _termLocationOptions,
mandatory: true),
_buildDropdownField(
_currencyController, "Currency", _currencyOptions,
_currencyController, l10n.currency, _currencyOptions,
mandatory: true),
_buildDropdownField(_acctSgmtCodeController,
"Account Segment Code", _acctSgmtCodeOptions,
l10n.accountSegmentCode, _acctSgmtCodeOptions,
mandatory: true),
],
),
@@ -502,35 +539,35 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Interest & Term Settings",
style: TextStyle(
Text(l10n.interestTermSettings,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildDropdownField(_interestPaymentMethodController,
"Interest Payment Method", _interestPaymentMethodOptions,
l10n.interestPaymentMethod, _interestPaymentMethodOptions,
mandatory: true),
_buildTextField(_taxFileNumberIndicatorController,
"Tax File Number Indicator"),
_buildTextField(_termLengthController, "Term Length"),
l10n.taxFileNumberIndicator),
_buildTextField(_termLengthController, l10n.termLength),
_buildDropdownField(
_termBasisController, "Term Basis", _termBasisOptions,
_termBasisController, l10n.termBasis, _termBasisOptions,
mandatory: true),
_buildTextField(_termValueDepositedController,
"Term Value Deposited",
l10n.termValueDeposited,
keyboardType: TextInputType.number,
mandatory: _productController.text != '28'),
_buildDropdownField(_interestFrequencyController,
"Interest Frequency", _interestFrequencyOptions),
_buildTextField(_termDaysController, "Term Days",
l10n.interestFrequency, _interestFrequencyOptions),
_buildTextField(_termDaysController, l10n.termDays,
keyboardType: TextInputType.number),
_buildTextField(_termMonthsController, "Term Months",
_buildTextField(_termMonthsController, l10n.termMonths,
keyboardType: TextInputType.number),
_buildTextField(_termYearsController, "Term Years",
_buildTextField(_termYearsController, l10n.termYears,
keyboardType: TextInputType.number, mandatory: true),
_buildTextField(
_nominationRequiredController, "Nomination Required"),
_nominationRequiredController, l10n.nominationRequired),
_buildTextField(
_printNomineeNameController, "Print Nominee Name"),
_printNomineeNameController, l10n.printNomineeName),
],
),
),
@@ -546,18 +583,18 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Recurring Deposit Settings",
style: TextStyle(
Text(l10n.recurringDepositSettings,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16),
_buildTextField(_rdInstallmentValueController,
"RD Installment Value",
l10n.rdInstallmentValue,
keyboardType: TextInputType.number),
_buildTextField(_monthlyRDInstallmentDueDayController,
"Monthly RD Installment Due Day",
l10n.monthlyRDInstallmentDueDay,
keyboardType: TextInputType.number),
_buildDropdownField(_rdInstlFreqController,
"RD Installment Frequency", _rdInstlFreqOptions),
l10n.rdInstallmentFrequency, _rdInstlFreqOptions),
],
),
),
@@ -585,9 +622,9 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
strokeWidth: 2,
),
)
: const Text(
"Proceed",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
: Text(
l10n.proceedButton,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 32),
@@ -603,6 +640,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
{bool readOnly = false,
bool mandatory = false,
void Function(String?)? onChanged}) {
final l10n = AppLocalizations.of(context);
String? currentValue =
options.containsKey(controller.text) ? controller.text : null;
@@ -630,7 +668,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
),
validator: (value) {
if (mandatory && (value == null || value.isEmpty)) {
return 'This field is required';
return l10n.fieldRequired;
}
return null;
},
@@ -649,6 +687,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
bool readOnly = false,
bool mandatory = false,
VoidCallback? onTap}) {
final l10n = AppLocalizations.of(context);
return Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: TextFormField(
@@ -665,7 +704,7 @@ class _CreateDepositScreenState extends State<CreateDepositScreen> {
keyboardType: keyboardType,
validator: (value) {
if (mandatory && (value == null || value.isEmpty)) {
return 'This field is required';
return l10n.fieldRequired;
}
return null;
},