Manage Beneficiary Services 2

This commit is contained in:
2025-08-10 11:18:00 +05:30
parent 83609fb778
commit 3024ddef15
2 changed files with 142 additions and 81 deletions

View File

@@ -1,17 +1,23 @@
// ignore_for_file: prefer_final_fields, unused_field
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:kmobile/api/services/beneficiary_service.dart';
import 'package:kmobile/data/models/ifsc.dart';
import 'package:kmobile/data/models/beneficiary.dart';
import 'package:kmobile/data/models/user.dart';
import 'beneficiary_result_page.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import '../../../di/injection.dart';
import '../../../l10n/app_localizations.dart';
class AddBeneficiaryScreen extends StatefulWidget {
const AddBeneficiaryScreen({super.key});
final List<User>? users;
final int? selectedIndex;
const AddBeneficiaryScreen({
super.key,
this.users,
this.selectedIndex,
});
@override
State<AddBeneficiaryScreen> createState() => _AddBeneficiaryScreen();
@@ -20,6 +26,7 @@ class AddBeneficiaryScreen extends StatefulWidget {
class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
final _formKey = GlobalKey<FormState>();
late User selectedUser = (widget.users ?? [])[widget.selectedIndex!];
final TextEditingController accountNumberController = TextEditingController();
final TextEditingController confirmAccountNumberController =
TextEditingController();
@@ -82,28 +89,83 @@ bool _isLoading = false; //for validateIFSC()
Future<void> _validateBeneficiary() async {
var beneficiaryService = getIt<BeneficiaryService>();
// start spinner / disable button
setState(() {
_isValidating = true;
_validationError = null;
});
try {
final name = await beneficiaryService
.validateBeneficiaryWithinBank(accountNumberController.text);
setState(() {
_beneficiaryName = name;
_isBeneficiaryValidated = true;
_isValidating = false;
});
} catch (e) {
setState(() {
_validationError = "Account Number not from KCCB";
_isValidating = false;
_isBeneficiaryValidated = false;
_beneficiaryName = null;
nameController.text = ''; // clear previous name
});
final String accountNo = accountNumberController.text.trim();
final String ifsc = ifscController.text.trim();
final String remitter = selectedUser.name ?? '';
final service = getIt<BeneficiaryService>();
try {
// Step 1: call validate API -> get refNo
final String? refNo = await service.validateBeneficiary(
accountNo: accountNo,
ifscCode: ifsc,
remitterName: remitter,
);
if (refNo == null || refNo.isEmpty) {
setState(() {
_validationError = 'Validation request failed. Please check details.';
_isBeneficiaryValidated = false;
});
return;
}
// Step 2: poll checkValidationStatus for up to 30 seconds
const int timeoutSeconds = 30;
const int intervalSeconds = 2;
int elapsed = 0;
String? foundName;
while (elapsed < timeoutSeconds) {
final String? name = await service.checkValidationStatus(refNo);
if (name != null && name.trim().isNotEmpty) {
foundName = name.trim();
break;
}
await Future.delayed(const Duration(seconds: intervalSeconds));
elapsed += intervalSeconds;
}
if (foundName != null) {
setState(() {
nameController.text = foundName!;
_isBeneficiaryValidated = true;
_validationError = null;
});
} else {
setState(() {
_validationError = 'Beneficiary not found within timeout.';
_isBeneficiaryValidated = false;
});
}
} catch (e, st) {
// handle unexpected errors
// print or log if you want
debugPrint('Error validating beneficiary: $e\n$st');
setState(() {
_validationError = 'Something went wrong. Please try again.';
_isBeneficiaryValidated = false;
});
} finally {
if (mounted) {
setState(() {
_isValidating = false;
});
}
}
}
String _selectedAccountType = 'Savings'; // default value
@@ -361,9 +423,8 @@ void validateAndAddBeneficiary() async {
),
),
),
//validate Beneficiary Button
if (!_isBeneficiaryValidated)
//Validate Beneficiary Name
if (!_isBeneficiaryValidated)
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: SizedBox(
@@ -372,7 +433,7 @@ void validateAndAddBeneficiary() async {
onPressed: _isValidating
? null
: () {
if (accountNumberController.text.length == 11 &&
if (
confirmAccountNumberController.text ==
accountNumberController.text) {
_validateBeneficiary();
@@ -388,20 +449,17 @@ void validateAndAddBeneficiary() async {
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Validate Beneficiary'),
),
),
),
//Beneficiary Name (Disabled)
const SizedBox(height: 24),
TextFormField(
controller: nameController,
enabled: false,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).beneficiaryName,
// prefixIcon: Icon(Icons.person),
border: const OutlineInputBorder(),
isDense: true,
filled: true,
@@ -410,18 +468,14 @@ void validateAndAddBeneficiary() async {
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black,
width: 2,
),
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.next,
validator: (value) => value == null || value.isEmpty
? AppLocalizations.of(context).nameRequired
: null,
),
),
const SizedBox(height: 24),
// 🔹 Account Type Dropdown
DropdownButtonFormField<String>(

View File

@@ -1,13 +1,17 @@
import 'package:flutter/material.dart';
import 'package:kmobile/data/models/beneficiary.dart';
import 'package:kmobile/features/beneficiaries/screens/add_beneficiary_screen.dart';
import '../../../data/models/user.dart';
import '../../../l10n/app_localizations.dart';
import '../../../di/injection.dart';
import 'package:kmobile/api/services/beneficiary_service.dart';
import 'package:shimmer/shimmer.dart';
//import 'package:kmobile/data/models/user.dart';
class ManageBeneficiariesScreen extends StatefulWidget {
// final List<User> users;
// final int selectedIndex;
const ManageBeneficiariesScreen({super.key});
@override
@@ -17,10 +21,13 @@ class ManageBeneficiariesScreen extends StatefulWidget {
class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
var service = getIt<BeneficiaryService>();
// late User selectedUser = widget.users[widget.selectedIndex];
//final BeneficiaryService _service = BeneficiaryService();
bool _isLoading = true;
int selectedAccountIndex = 0;
List<Beneficiary> _beneficiaries = [];
@override
void initState() {
super.initState();
@@ -101,7 +108,7 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AddBeneficiaryScreen(),
builder: (context) => AddBeneficiaryScreen(),
),
);
},