Fund Transfer page with Own Bank and Outside Bank modified

This commit is contained in:
2025-08-27 13:16:26 +05:30
parent a64e68d642
commit d3ad68b25c
6 changed files with 195 additions and 147 deletions

View File

@@ -1,5 +1,4 @@
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:kmobile/data/models/ifsc.dart';
import 'package:kmobile/data/models/beneficiary.dart';
@@ -105,4 +104,18 @@ class BeneficiaryService {
return [];
}
}
Future<void> deleteBeneficiary(String accountNo) async {
try {
final response = await _dio.delete('/api/beneficiary/$accountNo');
if (response.statusCode != 204) {
throw Exception('Failed to delete beneficiary');
}
} on DioException catch (e) {
throw Exception('Network error: ${e.message}');
} catch (e) {
throw Exception('Unexpected error: ${e.toString()}');
}
}
}

View File

@@ -0,0 +1,83 @@
import 'package:flutter/material.dart';
import 'package:kmobile/data/models/beneficiary.dart';
import 'package:kmobile/di/injection.dart';
import 'package:kmobile/widgets/bank_logos.dart';
import 'package:kmobile/api/services/beneficiary_service.dart';
class BeneficiaryDetailsScreen extends StatelessWidget {
final Beneficiary beneficiary;
BeneficiaryDetailsScreen({super.key, required this.beneficiary});
final service = getIt<BeneficiaryService>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Beneficiary Details'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 24,
backgroundColor: Colors.transparent,
child: getBankLogo(beneficiary.bankName),
),
const SizedBox(width: 16),
Text(
beneficiary.name,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(height: 24),
_buildDetailRow('Beneficiary Name', beneficiary.bankName ?? 'N/A'),
_buildDetailRow('Account No.', beneficiary.accountNo),
_buildDetailRow('Account Type', beneficiary.accountType),
_buildDetailRow('IFSC Code', beneficiary.ifscCode),
_buildDetailRow('Branch Name', beneficiary.branchName ?? 'N/A'),
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: () {
// Delete beneficiary option
},
icon: const Icon(Icons.delete),
label: const Text('Delete'),
),
],
),
],
),
),
);
}
Widget _buildDetailRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
Text(value),
],
),
);
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:kmobile/data/models/beneficiary.dart';
import 'package:kmobile/features/beneficiaries/screens/add_beneficiary_screen.dart';
import 'package:kmobile/features/beneficiaries/screens/beneficiary_details_screen.dart';
import '../../../l10n/app_localizations.dart';
import '../../../di/injection.dart';
import 'package:kmobile/api/services/beneficiary_service.dart';
@@ -88,6 +89,14 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => BeneficiaryDetailsScreen(beneficiary: item),
),
);
},
);
},
);

View File

@@ -13,7 +13,7 @@ import 'package:kmobile/features/auth/controllers/auth_state.dart';
import 'package:kmobile/features/customer_info/screens/customer_info_screen.dart';
import 'package:kmobile/features/beneficiaries/screens/manage_beneficiaries_screen.dart';
import 'package:kmobile/features/enquiry/screens/enquiry_screen.dart';
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart';
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_screen.dart';
import 'package:kmobile/features/profile/profile_screen.dart';
import 'package:kmobile/features/quick_pay/screens/quick_pay_screen.dart';
import 'package:kmobile/security/secure_storage.dart';
@@ -492,14 +492,13 @@ class _DashboardScreenState extends State<DashboardScreen> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
FundTransferBeneficiaryScreen(
creditAccountNo:
users[selectedAccountIndex]
.accountNo!,
remitterName:
users[selectedAccountIndex]
.name!)));
builder: (context) => FundTransferScreen(
creditAccountNo:
users[selectedAccountIndex]
.accountNo!,
remitterName:
users[selectedAccountIndex]
.name!)));
}, disable: false),
_buildQuickLink(
Symbols.server_person,

View File

@@ -10,8 +10,12 @@ import 'package:shimmer/shimmer.dart';
class FundTransferBeneficiaryScreen extends StatefulWidget {
final String creditAccountNo;
final String remitterName;
final bool isOwnBank;
const FundTransferBeneficiaryScreen(
{super.key, required this.creditAccountNo, required this.remitterName});
{super.key,
required this.creditAccountNo,
required this.remitterName,
required this.isOwnBank});
@override
State<FundTransferBeneficiaryScreen> createState() =>
@@ -33,7 +37,12 @@ class _FundTransferBeneficiaryScreenState
Future<void> _loadBeneficiaries() async {
final data = await service.fetchBeneficiaryList();
setState(() {
_beneficiaries = data;
_beneficiaries = data
.where((b) => widget.isOwnBank
? b.bankName ==
'THE KANGRA CENTRAL CO-OP BANK LIMITED' // Assuming 'KCCB' is your bank's name
: b.bankName != 'THE KANGRA CENTRAL CO-OP BANK LIMITED')
.toList();
_isLoading = false;
});
}

View File

@@ -1,153 +1,88 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../../l10n/app_localizations.dart';
class FundTransferScreen extends StatefulWidget {
const FundTransferScreen({super.key});
class FundTransferScreen extends StatelessWidget {
final String creditAccountNo;
final String remitterName;
@override
State<FundTransferScreen> createState() => _FundTransferScreen();
}
class _FundTransferScreen extends State<FundTransferScreen> {
String amount = "";
void onKeyTap(String key) {
setState(() {
if (key == 'back') {
if (amount.isNotEmpty) {
amount = amount.substring(0, amount.length - 1);
}
} else if (key == 'done') {
if (kDebugMode) {
print('${AppLocalizations.of(context).amountEntered} $amount');
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => const TransactionPinScreen(
// transactionData: {},
// transactionCode: 'TRANSFER'
// )));
}
} else {
amount += key;
}
});
}
Widget buildKey(String value) {
if (value == 'done') {
return GestureDetector(
onTap: () => onKeyTap(value),
child: const Icon(Symbols.check, size: 30),
);
} else if (value == 'back') {
return GestureDetector(
onTap: () => onKeyTap(value),
child: const Icon(Symbols.backspace, size: 30),
);
} else {
return GestureDetector(
onTap: () => onKeyTap(value),
child: Center(
child: Text(
value,
style: const TextStyle(fontSize: 24, color: Colors.black),
),
),
);
}
}
final keys = [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'done',
'0',
'back',
];
const FundTransferScreen({
super.key,
required this.creditAccountNo,
required this.remitterName,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Symbols.arrow_back_ios_new),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(
AppLocalizations.of(context).fundTransfer,
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: const [
Padding(
padding: EdgeInsets.only(right: 10.0),
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/avatar.jpg'),
// Replace with your image
radius: 20,
),
),
],
title: Text(AppLocalizations.of(context).fundTransfer),
),
body: Column(
body: ListView(
children: [
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(AppLocalizations.of(context).debitFrom),
const Text(
'0300015678903456',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
],
FundTransferManagementTile(
icon: Symbols.input_circle,
label: AppLocalizations.of(context).ownBank,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FundTransferBeneficiaryScreen(
creditAccountNo: creditAccountNo,
remitterName: remitterName,
isOwnBank: true,
),
),
);
},
),
const SizedBox(height: 20),
Text(
AppLocalizations.of(context).enterAmount,
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(12),
),
child: Text(
amount.isEmpty ? "0" : amount,
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
),
),
const Spacer(),
Container(
padding: const EdgeInsets.all(16.0),
color: Theme.of(context).scaffoldBackgroundColor,
child: GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.2,
children: keys.map((key) => buildKey(key)).toList(),
),
const Divider(height: 1),
FundTransferManagementTile(
icon: Symbols.output_circle,
label: AppLocalizations.of(context).outsideBank,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FundTransferBeneficiaryScreen(
creditAccountNo: creditAccountNo,
remitterName: remitterName,
isOwnBank: false,
),
),
);
},
),
const Divider(height: 1),
],
),
);
}
}
class FundTransferManagementTile extends StatelessWidget {
final IconData icon;
final String label;
final VoidCallback onTap;
final bool disable;
const FundTransferManagementTile({
super.key,
required this.icon,
required this.label,
required this.onTap,
this.disable = false,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(icon),
title: Text(label),
trailing: const Icon(Symbols.arrow_right, size: 20),
onTap: onTap,
enabled: !disable,
);
}
}