import 'dart:convert'; 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'; class APYRegisterScreen extends StatefulWidget { final Map? initialData; const APYRegisterScreen({super.key, this.initialData}); @override State createState() => _APYRegisterScreenState(); } class _APYRegisterScreenState extends State { final _formKey = GlobalKey(); // Helper to format initial date string (DDMMYYYY -> DD/MM/YYYY) String _formatInitialDate(dynamic date) { if (date == null) return ''; String dateStr = date.toString(); if (dateStr.length == 8) { return "${dateStr.substring(0, 2)}/${dateStr.substring(2, 4)}/${dateStr.substring(4)}"; } return dateStr; } // Controllers initialized strictly from initialData where available, otherwise empty. 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: _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()); // Fields that must be filled by the user (no defaults) late final _marriedController = TextEditingController(); 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 _guardianNameController = TextEditingController(); late final _fatcaController = TextEditingController(); late final _birthCountryController = TextEditingController(); late final _citizenshipCountryController = TextEditingController(); late final _taxResidenceCountryController = TextEditingController(); late final _usPersonController = TextEditingController(); late final _secondNomineeNameController = TextEditingController(); late final _secondNomineeMinorController = TextEditingController(); late final _secondNomineeRelationController = TextEditingController(); late final _fatcaCountController = TextEditingController(); late final _docCitizenshipFlagController = TextEditingController(); late final _reasonNoEvidenceController = TextEditingController(); late final _docNameEvidenceController = TextEditingController(); final Map _yesNoOptions = { 'Y': 'Yes', 'N': 'No', }; final Map _titleOptions = { '01': 'Mr.', '02': 'Mrs.', '03': 'Miss', }; final Map _genderOptions = { 'M': 'Male', 'F': 'Female', 'O': 'Other', }; final Map _pensionOptions = { '1000': '₹1000', '2000': '₹2000', '3000': '₹3000', '4000': '₹4000', '5000': '₹5000', }; final Map _collectionChannelOptions = { '1': 'Bank', }; Map _getPeriodicityOptions(AppLocalizations l10n) => { 'C': l10n.monthly, 'Q': l10n.quarterly, 'H': l10n.halfYearly, }; // Contribution Calculation Map final Map> _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(); _secondNomineeNameController.dispose(); _secondNomineeMinorController.dispose(); _secondNomineeRelationController.dispose(); _fatcaCountController.dispose(); _docCitizenshipFlagController.dispose(); _reasonNoEvidenceController.dispose(); _docNameEvidenceController.dispose(); _modeOfCollectionController.dispose(); super.dispose(); } Future _selectDate(BuildContext context, TextEditingController controller) async { final DateTime? picked = await showDatePicker( context: context, 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() async { if (_formKey.currentState!.validate()) { showDialog( context: context, barrierDismissible: false, builder: (context) => const Center(child: CircularProgressIndicator()), ); try { final yojnaService = getIt(); 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'), ), ], ), ); } } } @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 Details Card( elevation: 2, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l10n.personaldetails, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 16), _buildDropdownField( _titleController, l10n.customerTitle, _titleOptions), _buildTextField( _firstNameController, l10n.customerFirstName), _buildTextField( _middleNameController, l10n.customerMiddleName), _buildTextField( _lastNameController, l10n.customerLastName), _buildTextField(_customerNoController, l10n.customerNo), _buildTextField(_accountNoController, l10n.accountNumber, keyboardType: TextInputType.number), _buildTextField(_balanceController, l10n.availableBalance, keyboardType: TextInputType.number), _buildTextField(_dobController, l10n.customerDobFormat, mandatory: true, onTap: () => _selectDate(context, _dobController)), _buildDropdownField( _genderController, l10n.gender, _genderOptions), _buildTextField(_mobileController, l10n.mobileNumber, keyboardType: TextInputType.phone), _buildTextField(_emailController, l10n.emailId, keyboardType: TextInputType.emailAddress), _buildTextField(_aadhaarController, l10n.aadhaarNo, keyboardType: TextInputType.number), _buildTextField(_pincodeController, l10n.pincode, keyboardType: TextInputType.number), _buildDropdownField( _marriedController, l10n.marriedYesNo, _yesNoOptions, 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, mandatory: true), _buildTextField(_nomineeRelationController, l10n.relationWithSubscriber, mandatory: true), _buildDropdownField(_nomineeMinorController, l10n.nomineeMinor, _yesNoOptions, mandatory: true, onChanged: (val) { setState(() { _nomineeMinorController.text = val ?? ''; }); }), if (_nomineeMinorController.text == 'Y') ...[ _buildTextField(_nomineeDobController, l10n.nomineeDob, mandatory: true, onTap: () => _selectDate(context, _nomineeDobController)), _buildTextField( _guardianNameController, l10n.guardianName, 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, 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), _buildTextField(_modeOfCollectionController, l10n.modeOfCollection), ], ), ), ), 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( _birthCountryController, l10n.countryOfBirth), _buildTextField(_citizenshipCountryController, l10n.countryOfCitizenship), _buildTextField(_taxResidenceCountryController, l10n.countryOfTaxResidence), _buildDropdownField(_usPersonController, l10n.usPersonFlag, _yesNoOptions), _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, l10n.pensionAmount, _pensionOptions, mandatory: true, onChanged: (val) { setState(() { _pensionAmountController.text = val ?? ''; }); }), _buildDropdownField(_contributionTypeController, l10n.periodicity, _getPeriodicityOptions(l10n), mandatory: true, onChanged: (val) { setState(() { _contributionTypeController.text = val ?? ''; }); }), _buildTextField( _debitDateController, l10n.subsequentDebitDate, mandatory: true, onTap: () => _selectDate(context, _debitDateController)), ], ), ), ), const SizedBox(height: 16), // Tile 6: Contribution Amount Summary 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 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( value: currentValue, onChanged: readOnly ? null : (newValue) { if (newValue != null) { setState(() { controller.text = newValue; }); } if (onChanged != null) { onChanged(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( value: entry.key, child: Text(entry.value), ); }).toList(), ), ); } Widget _buildTextField(TextEditingController controller, String label, {TextInputType keyboardType = TextInputType.text, bool readOnly = false, bool mandatory = false, VoidCallback? onTap}) { return Padding( padding: const EdgeInsets.only(bottom: 16.0), child: TextFormField( controller: controller, readOnly: readOnly || onTap != null, onTap: onTap, decoration: InputDecoration( labelText: mandatory ? '$label *' : label, border: const OutlineInputBorder(), suffixIcon: onTap != null ? const Icon(Icons.calendar_today) : null, 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; }, ), ); } }