Edit Limit for beneficiaries and APY Register UI
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:kmobile/data/models/beneficiary.dart';
|
||||
import 'package:kmobile/di/injection.dart';
|
||||
import 'package:kmobile/widgets/bank_logos.dart';
|
||||
@@ -6,16 +7,39 @@ import 'package:kmobile/api/services/beneficiary_service.dart';
|
||||
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
|
||||
class BeneficiaryDetailsScreen extends StatelessWidget {
|
||||
class BeneficiaryDetailsScreen extends StatefulWidget {
|
||||
final Beneficiary beneficiary;
|
||||
|
||||
BeneficiaryDetailsScreen({super.key, required this.beneficiary});
|
||||
const BeneficiaryDetailsScreen({super.key, required this.beneficiary});
|
||||
|
||||
@override
|
||||
State<BeneficiaryDetailsScreen> createState() =>
|
||||
_BeneficiaryDetailsScreenState();
|
||||
}
|
||||
|
||||
class _BeneficiaryDetailsScreenState extends State<BeneficiaryDetailsScreen> {
|
||||
final service = getIt<BeneficiaryService>();
|
||||
late String _currentLimit;
|
||||
final _limitController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_currentLimit = (widget.beneficiary.transactionLimit == null ||
|
||||
widget.beneficiary.transactionLimit!.isEmpty)
|
||||
? 'N/A'
|
||||
: widget.beneficiary.transactionLimit!;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_limitController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _deleteBeneficiary(BuildContext context) async {
|
||||
try {
|
||||
await service.deleteBeneficiary(beneficiary.accountNo);
|
||||
await service.deleteBeneficiary(widget.beneficiary.accountNo);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -77,6 +101,73 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showEditLimitDialog() async {
|
||||
_limitController.text = _currentLimit == 'N/A' ? '' : _currentLimit;
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (dialogContext) {
|
||||
final localizations = AppLocalizations.of(dialogContext);
|
||||
final theme = Theme.of(dialogContext);
|
||||
return AlertDialog(
|
||||
title: Text(localizations.editLimit),
|
||||
content: TextField(
|
||||
controller: _limitController,
|
||||
autofocus: true,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'^\d+')),
|
||||
],
|
||||
decoration: InputDecoration(
|
||||
labelText: localizations.limitAmount,
|
||||
prefixText: '₹',
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
child: Text(localizations.cancel),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final value = _limitController.text;
|
||||
if (value.isEmpty || int.tryParse(value) == null) return;
|
||||
|
||||
try {
|
||||
await service.updateLimit(
|
||||
beneficiaryAccountNo: widget.beneficiary.accountNo,
|
||||
newLimit: value,
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_currentLimit = value;
|
||||
});
|
||||
Navigator.of(dialogContext).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(localizations.limitUpdatedSuccess),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
Navigator.of(dialogContext).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("${localizations.error}: $e"),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
backgroundColor: theme.colorScheme.error,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(localizations.save),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -96,11 +187,11 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
||||
CircleAvatar(
|
||||
radius: 24,
|
||||
backgroundColor: Colors.transparent,
|
||||
child: getBankLogo(beneficiary.bankName, context),
|
||||
child: getBankLogo(widget.beneficiary.bankName, context),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
beneficiary.name,
|
||||
widget.beneficiary.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
@@ -108,29 +199,28 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_buildDetailRow('${AppLocalizations.of(context).bankName} ',
|
||||
beneficiary.bankName ?? 'N/A'),
|
||||
widget.beneficiary.bankName ?? 'N/A'),
|
||||
_buildDetailRow(
|
||||
'${AppLocalizations.of(context).accountNumber} ',
|
||||
beneficiary.accountNo),
|
||||
widget.beneficiary.accountNo),
|
||||
_buildDetailRow(
|
||||
'${AppLocalizations.of(context).accountType} ',
|
||||
beneficiary.accountType),
|
||||
widget.beneficiary.accountType),
|
||||
_buildDetailRow('${AppLocalizations.of(context).ifscCode} ',
|
||||
beneficiary.ifscCode),
|
||||
widget.beneficiary.ifscCode),
|
||||
_buildDetailRow('${AppLocalizations.of(context).branchName} ',
|
||||
beneficiary.branchName ?? 'N/A'),
|
||||
_buildDetailRow("Beneficiary Transactional Limit", beneficiary.transactionLimit ?? 'N/A'),
|
||||
widget.beneficiary.branchName ?? 'N/A'),
|
||||
_buildDetailRow(
|
||||
"Beneficiary Transactional Limit", _currentLimit),
|
||||
const Spacer(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
// ElevatedButton.icon(
|
||||
// onPressed: () {
|
||||
// // Set Transaction Limit for this beneficiary
|
||||
// },
|
||||
// icon: const Icon(Icons.currency_rupee),
|
||||
// label: const Text('Set Limit'),
|
||||
// ),
|
||||
ElevatedButton.icon(
|
||||
onPressed: _showEditLimitDialog,
|
||||
icon: const Icon(Icons.currency_rupee),
|
||||
label: Text(AppLocalizations.of(context).editLimit),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// Delete beneficiary option
|
||||
@@ -184,3 +274,4 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
396
lib/features/yojna/screens/apy_register_screen.dart
Normal file
396
lib/features/yojna/screens/apy_register_screen.dart
Normal file
@@ -0,0 +1,396 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/l10n/app_localizations.dart';
|
||||
|
||||
class APYRegisterScreen extends StatefulWidget {
|
||||
final Map<String, dynamic>? initialData;
|
||||
const APYRegisterScreen({super.key, this.initialData});
|
||||
|
||||
@override
|
||||
State<APYRegisterScreen> createState() => _APYRegisterScreenState();
|
||||
}
|
||||
|
||||
class _APYRegisterScreenState extends State<APYRegisterScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
// Controllers
|
||||
late final _titleController = TextEditingController(text: widget.initialData?['customertitle']?.toString());
|
||||
late final _firstNameController = TextEditingController(text: widget.initialData?['customerfirstname']?.toString());
|
||||
late final _middleNameController = TextEditingController(text: widget.initialData?['customermiddlename']?.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: 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');
|
||||
late final _ageOfJoiningController = TextEditingController(text: widget.initialData?['ageofjoining']?.toString());
|
||||
late final _spouseNameController = TextEditingController(text: widget.initialData?['nameofspouse']?.toString());
|
||||
late final _incomeTaxPayerController = TextEditingController(text: widget.initialData?['whetherincometaxpayer']?.toString());
|
||||
late final _otherSchemeController = TextEditingController(text: widget.initialData?['beneficaryofothersociatysecurityschemes']?.toString());
|
||||
late final _collectionChannelController = TextEditingController(text: widget.initialData?['collectionchannel']?.toString() ?? '1');
|
||||
late final _contributionTypeController = TextEditingController(text: widget.initialData?['contributionType']?.toString() ?? 'C');
|
||||
late final _debitDateController = TextEditingController(text: widget.initialData?['subsequentContributionDebitDate']?.toString());
|
||||
|
||||
late final _nomineeNameController = TextEditingController(text: widget.initialData?['nomineename']?.toString());
|
||||
late final _nomineeRelationController = TextEditingController(text: widget.initialData?['relationwithsubscriber']?.toString());
|
||||
late final _nomineeMinorController = TextEditingController(text: widget.initialData?['nomineeminor']?.toString() ?? 'N');
|
||||
late final _nomineeDobController = TextEditingController();
|
||||
late final _guardianNameController = TextEditingController();
|
||||
|
||||
late final _fatcaController = TextEditingController(text: widget.initialData?['fatcacrsapplicable']?.toString());
|
||||
late final _birthCountryController = TextEditingController(text: widget.initialData?['countryofbirth']?.toString());
|
||||
late final _citizenshipCountryController = TextEditingController(text: widget.initialData?['countryofcitizenship']?.toString());
|
||||
late final _taxResidenceCountryController = TextEditingController(text: widget.initialData?['countryofresidencefortaxpurpose']?.toString());
|
||||
late final _usPersonController = TextEditingController(text: widget.initialData?['uspersonflag']?.toString());
|
||||
|
||||
final Map<String, String> _yesNoOptions = {
|
||||
'Y': 'Yes',
|
||||
'N': 'No',
|
||||
};
|
||||
|
||||
final Map<String, String> _titleOptions = {
|
||||
'01': 'Mr.',
|
||||
'02': 'Mrs.',
|
||||
'03': 'Miss',
|
||||
};
|
||||
|
||||
final Map<String, String> _pensionOptions = {
|
||||
'1000': '₹1000',
|
||||
'2000': '₹2000',
|
||||
'3000': '₹3000',
|
||||
'4000': '₹4000',
|
||||
'5000': '₹5000',
|
||||
};
|
||||
|
||||
final Map<String, String> _collectionChannelOptions = {
|
||||
'1': 'Bank',
|
||||
};
|
||||
|
||||
Map<String, String> _getPeriodicityOptions(AppLocalizations l10n) => {
|
||||
'C': l10n.monthly,
|
||||
'Q': l10n.quarterly,
|
||||
'H': l10n.halfYearly,
|
||||
};
|
||||
|
||||
// Contribution Calculation Map
|
||||
final Map<String, Map<String, String>> _contributionRates = {
|
||||
'C': {
|
||||
'1000': '90',
|
||||
'2000': '178',
|
||||
'3000': '268',
|
||||
'4000': '356',
|
||||
'5000': '446',
|
||||
},
|
||||
'Q': {
|
||||
'1000': '268',
|
||||
'2000': '530',
|
||||
'3000': '1061',
|
||||
'4000': '356', // Following prompt's example exactly
|
||||
'5000': '1329',
|
||||
},
|
||||
'H': {
|
||||
'1000': '531',
|
||||
'2000': '1050',
|
||||
'3000': '1582',
|
||||
'4000': '2101',
|
||||
'5000': '2632',
|
||||
},
|
||||
};
|
||||
|
||||
String get _calculatedContribution {
|
||||
final periodicity = _contributionTypeController.text;
|
||||
final amount = _pensionAmountController.text;
|
||||
return _contributionRates[periodicity]?[amount] ?? '0';
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_titleController.dispose();
|
||||
_firstNameController.dispose();
|
||||
_middleNameController.dispose();
|
||||
_lastNameController.dispose();
|
||||
_customerNoController.dispose();
|
||||
_accountNoController.dispose();
|
||||
_balanceController.dispose();
|
||||
_dobController.dispose();
|
||||
_genderController.dispose();
|
||||
_marriedController.dispose();
|
||||
_mobileController.dispose();
|
||||
_emailController.dispose();
|
||||
_aadhaarController.dispose();
|
||||
_pincodeController.dispose();
|
||||
_pensionAmountController.dispose();
|
||||
_ageOfJoiningController.dispose();
|
||||
_spouseNameController.dispose();
|
||||
_incomeTaxPayerController.dispose();
|
||||
_otherSchemeController.dispose();
|
||||
_collectionChannelController.dispose();
|
||||
_contributionTypeController.dispose();
|
||||
_debitDateController.dispose();
|
||||
_nomineeNameController.dispose();
|
||||
_nomineeRelationController.dispose();
|
||||
_nomineeMinorController.dispose();
|
||||
_nomineeDobController.dispose();
|
||||
_guardianNameController.dispose();
|
||||
_fatcaController.dispose();
|
||||
_birthCountryController.dispose();
|
||||
_citizenshipCountryController.dispose();
|
||||
_taxResidenceCountryController.dispose();
|
||||
_usPersonController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _isFetched(String key) {
|
||||
return widget.initialData != null &&
|
||||
widget.initialData!.containsKey(key) &&
|
||||
widget.initialData![key]?.toString().isNotEmpty == true;
|
||||
}
|
||||
|
||||
void _handleRegister() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Registration logic to be implemented')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(l10n.apyRegistration),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Tile 1: Customer & APY Details
|
||||
Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(l10n.details,
|
||||
style: const TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
_buildDropdownField(_titleController, l10n.customerTitle,
|
||||
_titleOptions,
|
||||
readOnly: _isFetched('customertitle')),
|
||||
_buildTextField(
|
||||
_firstNameController, l10n.customerFirstName,
|
||||
readOnly: _isFetched('customerfirstname')),
|
||||
_buildTextField(
|
||||
_middleNameController, l10n.customerMiddleName,
|
||||
readOnly: _isFetched('customermiddlename')),
|
||||
_buildTextField(
|
||||
_lastNameController, l10n.customerLastName,
|
||||
readOnly: _isFetched('customerlastname')),
|
||||
_buildTextField(_accountNoController, l10n.accountNumber,
|
||||
keyboardType: TextInputType.number,
|
||||
readOnly: _isFetched('accountno')),
|
||||
_buildTextField(
|
||||
_balanceController, l10n.availableBalance,
|
||||
keyboardType: TextInputType.number,
|
||||
readOnly: _isFetched('availablebalance')),
|
||||
_buildTextField(_dobController, l10n.customerDobFormat,
|
||||
mandatory: true, readOnly: _isFetched('customerdob')),
|
||||
_buildTextField(_emailController, l10n.emailId,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
readOnly: _isFetched('emailid')),
|
||||
_buildDropdownField(
|
||||
_marriedController, l10n.marriedYesNo, _yesNoOptions,
|
||||
mandatory: true),
|
||||
_buildTextField(_nomineeNameController, l10n.nomineeName,
|
||||
mandatory: true),
|
||||
_buildDropdownField(_nomineeMinorController,
|
||||
l10n.nomineeMinor, _yesNoOptions,
|
||||
mandatory: true, onChanged: (val) {
|
||||
setState(() {
|
||||
_nomineeMinorController.text = val ?? 'N';
|
||||
});
|
||||
}),
|
||||
if (_nomineeMinorController.text == 'Y') ...[
|
||||
_buildTextField(_nomineeDobController, l10n.nomineeDob,
|
||||
mandatory: true),
|
||||
_buildTextField(
|
||||
_guardianNameController, l10n.guardianName,
|
||||
mandatory: true),
|
||||
],
|
||||
_buildDropdownField(_otherSchemeController,
|
||||
l10n.isBeneficiaryOtherScheme, _yesNoOptions,
|
||||
mandatory: true),
|
||||
_buildDropdownField(_incomeTaxPayerController,
|
||||
l10n.isIncomeTaxPayer, _yesNoOptions,
|
||||
mandatory: true),
|
||||
_buildTextField(_spouseNameController, l10n.nameOfSpouse,
|
||||
mandatory: true),
|
||||
_buildTextField(_ageOfJoiningController, l10n.ageOfJoining,
|
||||
keyboardType: TextInputType.number, mandatory: true),
|
||||
_buildDropdownField(_collectionChannelController,
|
||||
l10n.collectionChannel, _collectionChannelOptions,
|
||||
mandatory: true),
|
||||
_buildDropdownField(
|
||||
_fatcaController, l10n.fatcaApplicable, _yesNoOptions),
|
||||
_buildTextField(
|
||||
_birthCountryController, l10n.countryOfBirth),
|
||||
_buildTextField(
|
||||
_citizenshipCountryController, l10n.countryOfCitizenship),
|
||||
_buildTextField(_taxResidenceCountryController,
|
||||
l10n.countryOfTaxResidence),
|
||||
_buildDropdownField(
|
||||
_usPersonController, l10n.usPersonFlag, _yesNoOptions),
|
||||
const Divider(height: 32),
|
||||
_buildDropdownField(_pensionAmountController,
|
||||
l10n.pensionAmount, _pensionOptions,
|
||||
mandatory: true, onChanged: (val) {
|
||||
setState(() {
|
||||
_pensionAmountController.text = val ?? '1000';
|
||||
});
|
||||
}),
|
||||
_buildDropdownField(_contributionTypeController,
|
||||
l10n.periodicity, _getPeriodicityOptions(l10n),
|
||||
mandatory: true, onChanged: (val) {
|
||||
setState(() {
|
||||
_contributionTypeController.text = val ?? 'C';
|
||||
});
|
||||
}),
|
||||
_buildTextField(
|
||||
_debitDateController, l10n.subsequentDebitDate,
|
||||
mandatory: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
// Tile 2: Contribution Amount
|
||||
Card(
|
||||
elevation: 2,
|
||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'${l10n.contributionAmount} (${_getPeriodicityOptions(l10n)[_contributionTypeController.text]})',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer)),
|
||||
const SizedBox(height: 8),
|
||||
Text('₹ $_calculatedContribution',
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: _handleRegister,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
|
||||
foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
l10n.register,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDropdownField(
|
||||
TextEditingController controller, String label, Map<String, String> options,
|
||||
{bool readOnly = false, bool mandatory = false, void Function(String?)? onChanged}) {
|
||||
String? currentValue =
|
||||
options.containsKey(controller.text) ? controller.text : null;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: currentValue,
|
||||
onChanged: readOnly ? null : (newValue) {
|
||||
if (onChanged != null) {
|
||||
onChanged(newValue);
|
||||
} else {
|
||||
setState(() {
|
||||
controller.text = newValue ?? '';
|
||||
});
|
||||
}
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: mandatory ? '$label *' : label,
|
||||
border: const OutlineInputBorder(),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
|
||||
),
|
||||
validator: (value) {
|
||||
if (mandatory && (value == null || value.isEmpty)) {
|
||||
return 'This field is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
items: options.entries.map((entry) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: entry.key,
|
||||
child: Text(entry.value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTextField(TextEditingController controller, String label,
|
||||
{TextInputType keyboardType = TextInputType.text,
|
||||
bool readOnly = false,
|
||||
bool mandatory = false}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: TextFormField(
|
||||
controller: controller,
|
||||
readOnly: readOnly,
|
||||
decoration: InputDecoration(
|
||||
labelText: mandatory ? '$label *' : label,
|
||||
border: const OutlineInputBorder(),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
|
||||
),
|
||||
keyboardType: keyboardType,
|
||||
validator: (value) {
|
||||
if (mandatory && (value == null || value.isEmpty)) {
|
||||
return 'This field is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/data/models/user.dart';
|
||||
import 'package:kmobile/features/yojna/screens/apy_register_screen.dart';
|
||||
import 'package:kmobile/l10n/app_localizations.dart';
|
||||
|
||||
class APYScreen extends StatefulWidget {
|
||||
@@ -18,6 +19,7 @@ class APYScreen extends StatefulWidget {
|
||||
class _APYScreenState extends State<APYScreen> {
|
||||
User? _selectedAccount;
|
||||
List<User> _filteredUsers = [];
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -54,58 +56,132 @@ class _APYScreenState extends State<APYScreen> {
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
l10n.apyDescription,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
l10n.apyDescription,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DropdownButtonFormField<User>(
|
||||
value: _selectedAccount,
|
||||
decoration: InputDecoration(
|
||||
labelText: l10n.accountNumber,
|
||||
border: const OutlineInputBorder(),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 20, horizontal: 12),
|
||||
const SizedBox(height: 16),
|
||||
Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DropdownButtonFormField<User>(
|
||||
value: _selectedAccount,
|
||||
decoration: InputDecoration(
|
||||
labelText: l10n.accountNumber,
|
||||
border: const OutlineInputBorder(),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 20, horizontal: 12),
|
||||
),
|
||||
items: _filteredUsers.map((user) {
|
||||
return DropdownMenuItem<User>(
|
||||
value: user,
|
||||
child: Text(user.accountNo.toString()),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (User? newUser) {
|
||||
setState(() {
|
||||
_selectedAccount = newUser;
|
||||
});
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return l10n.accountNumberRequired;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
items: _filteredUsers.map((user) {
|
||||
return DropdownMenuItem<User>(
|
||||
value: user,
|
||||
child: Text(user.accountNo.toString()),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (User? newUser) {
|
||||
setState(() {
|
||||
_selectedAccount = newUser;
|
||||
});
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return l10n.accountNumberRequired;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
final mockData = {
|
||||
"accountno": _selectedAccount?.accountNo ?? "50069506061",
|
||||
"customerfirstname": "TAMANA",
|
||||
"customermiddlename": "",
|
||||
"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(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => APYRegisterScreen(initialData: mockData),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.primaryContainer,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
minimumSize: const Size(double.infinity, 50),
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
l10n.proceedButton,
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user