chequemanagement #1
This commit is contained in:
@@ -105,7 +105,7 @@ class BranchService {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return Branch.listFromJson(response.data);
|
return Branch.listFromJson(response.data);
|
||||||
} else {
|
} else {
|
||||||
throw Exception("Failed to fetch beneficiaries");
|
throw Exception("Failed to fetch");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
96
lib/api/services/cheque_service.dart
Normal file
96
lib/api/services/cheque_service.dart
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
class Cheque {
|
||||||
|
final String? type;
|
||||||
|
final String? InstrType;
|
||||||
|
final String? Date;
|
||||||
|
final String? branchCode;
|
||||||
|
final String? fromCheque;
|
||||||
|
final String? toCheque;
|
||||||
|
final String? Chequescount;
|
||||||
|
final String? ChequeNumber;
|
||||||
|
final String? transactionCode;
|
||||||
|
final String? amount;
|
||||||
|
final String? status;
|
||||||
|
final String? stopIssueDate;
|
||||||
|
final String? StopExpiryDate;
|
||||||
|
|
||||||
|
Cheque({
|
||||||
|
this.type,
|
||||||
|
this.InstrType,
|
||||||
|
this.Date,
|
||||||
|
this.branchCode,
|
||||||
|
this.fromCheque,
|
||||||
|
this.toCheque,
|
||||||
|
this.Chequescount,
|
||||||
|
this.ChequeNumber,
|
||||||
|
this.transactionCode,
|
||||||
|
this.amount,
|
||||||
|
this.status,
|
||||||
|
this.stopIssueDate,
|
||||||
|
this.StopExpiryDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Cheque.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Cheque(
|
||||||
|
type: json['type'] ?? '',
|
||||||
|
InstrType: json['InstrType'] ?? '',
|
||||||
|
Date: json['Date'] ?? '',
|
||||||
|
branchCode: json['branchCode'] ?? '',
|
||||||
|
fromCheque: json['fromCheque'] ?? '',
|
||||||
|
toCheque: json['toCheque'] ?? '',
|
||||||
|
Chequescount: json['Chequescount'] ?? '',
|
||||||
|
ChequeNumber: json['ChequeNumber'] ?? '',
|
||||||
|
transactionCode: json['transactionCode'] ?? '',
|
||||||
|
amount: json['amount'] ?? '',
|
||||||
|
status: json['status'] ?? '',
|
||||||
|
stopIssueDate: json['stopIssueDate'] ?? '',
|
||||||
|
StopExpiryDate: json['StopExpiryDate'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Cheque> listFromJson(List<dynamic> jsonList) {
|
||||||
|
final chequeList =
|
||||||
|
jsonList.map((cheque) => Cheque.fromJson(cheque)).toList();
|
||||||
|
return chequeList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChequeService {
|
||||||
|
final Dio _dio;
|
||||||
|
ChequeService(this._dio);
|
||||||
|
|
||||||
|
Future<List<Cheque>> ChequeEnquiry(
|
||||||
|
{required String accountNumber,
|
||||||
|
required String instrType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final response = await _dio.get(
|
||||||
|
"/api/cheque",
|
||||||
|
queryParameters: {
|
||||||
|
'accountNumber': accountNumber,
|
||||||
|
'instrumentType': instrType,
|
||||||
|
},
|
||||||
|
options: Options(
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
if (response.data is Map<String, dynamic> && response.data.containsKey('records')) {
|
||||||
|
final records = response.data['records'];
|
||||||
|
if (records is List) {
|
||||||
|
return Cheque.listFromJson(records);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Exception("Unexpected API response format: 'records' list not found or malformed");
|
||||||
|
} else {
|
||||||
|
throw Exception("Failed to fetch");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error in ChequeEnquiry: $e');
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:kmobile/api/services/branch_service.dart';
|
import 'package:kmobile/api/services/branch_service.dart';
|
||||||
|
import 'package:kmobile/api/services/cheque_service.dart';
|
||||||
import 'package:kmobile/api/services/limit_service.dart';
|
import 'package:kmobile/api/services/limit_service.dart';
|
||||||
import 'package:kmobile/api/services/rtgs_service.dart';
|
import 'package:kmobile/api/services/rtgs_service.dart';
|
||||||
import 'package:kmobile/api/services/neft_service.dart';
|
import 'package:kmobile/api/services/neft_service.dart';
|
||||||
@@ -56,6 +57,7 @@ Future<void> setupDependencies() async {
|
|||||||
getIt.registerSingleton<RtgsService>(RtgsService(getIt<Dio>()));
|
getIt.registerSingleton<RtgsService>(RtgsService(getIt<Dio>()));
|
||||||
getIt.registerSingleton<ImpsService>(ImpsService(getIt<Dio>()));
|
getIt.registerSingleton<ImpsService>(ImpsService(getIt<Dio>()));
|
||||||
getIt.registerSingleton<BranchService>(BranchService(getIt<Dio>()));
|
getIt.registerSingleton<BranchService>(BranchService(getIt<Dio>()));
|
||||||
|
getIt.registerSingleton<ChequeService>(ChequeService(getIt<Dio>()));
|
||||||
getIt.registerLazySingleton<ChangePasswordService>(
|
getIt.registerLazySingleton<ChangePasswordService>(
|
||||||
() => ChangePasswordService(getIt<Dio>()),
|
() => ChangePasswordService(getIt<Dio>()),
|
||||||
);
|
);
|
||||||
@@ -74,9 +76,9 @@ Dio _createDioClient() {
|
|||||||
final dio = Dio(
|
final dio = Dio(
|
||||||
BaseOptions(
|
BaseOptions(
|
||||||
baseUrl:
|
baseUrl:
|
||||||
//'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', //test
|
'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com', //test
|
||||||
//'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod
|
//'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod
|
||||||
'https://kccbmbnk.net', //prod small
|
//'https://kccbmbnk.net', //prod small
|
||||||
connectTimeout: const Duration(seconds: 60),
|
connectTimeout: const Duration(seconds: 60),
|
||||||
receiveTimeout: const Duration(seconds: 60),
|
receiveTimeout: const Duration(seconds: 60),
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:kmobile/features/enquiry/screens/enquiry_screen.dart';
|
import 'package:kmobile/data/models/user.dart';
|
||||||
|
import 'package:kmobile/features/cheque/screens/cheque_status_screen.dart';
|
||||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
import '../../../l10n/app_localizations.dart';
|
import '../../../l10n/app_localizations.dart';
|
||||||
|
|
||||||
class ChequeManagementScreen extends StatefulWidget {
|
class ChequeManagementScreen extends StatefulWidget {
|
||||||
const ChequeManagementScreen({super.key});
|
final List<User> users;
|
||||||
|
final int selectedIndex;
|
||||||
|
const ChequeManagementScreen({
|
||||||
|
super.key,
|
||||||
|
required this.users,
|
||||||
|
required this.selectedIndex,});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ChequeManagementScreen> createState() => _ChequeManagementScreen();
|
State<ChequeManagementScreen> createState() => _ChequeManagementScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
||||||
|
List<User> get users => widget.users;
|
||||||
|
int get selectedAccountIndex => widget.selectedIndex;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -22,52 +31,55 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
|||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
ListView(
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
const SizedBox(height: 15),
|
child: Column(
|
||||||
ChequeManagementTile(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
icon: Symbols.add,
|
children: [
|
||||||
label: AppLocalizations.of(context).requestChequeBook,
|
Expanded(
|
||||||
onTap: () {},
|
child: ChequeManagementCardTile(
|
||||||
),
|
icon: Symbols.add,
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
label: AppLocalizations.of(context).requestChequeBook,
|
||||||
ChequeManagementTile(
|
subtitle: "Apply for a new cheque book",
|
||||||
icon: Symbols.data_alert,
|
onTap: () {},
|
||||||
label: AppLocalizations.of(context).enquiry,
|
),
|
||||||
onTap: () {
|
),
|
||||||
Navigator.push(
|
Expanded(
|
||||||
context,
|
child: ChequeManagementCardTile(
|
||||||
MaterialPageRoute(
|
icon: Symbols.data_alert,
|
||||||
builder: (context) => const EnquiryScreen()),
|
label: "Cheque History",
|
||||||
);
|
subtitle: "View the status of your issued cheques",
|
||||||
},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
),
|
||||||
ChequeManagementTile(
|
Expanded(
|
||||||
icon: Symbols.approval_delegation,
|
child: ChequeManagementCardTile(
|
||||||
label: AppLocalizations.of(context).chequeDeposit,
|
icon: Symbols.front_hand,
|
||||||
onTap: () {},
|
label: AppLocalizations.of(context).stopCheque,
|
||||||
),
|
subtitle: "Stop payment for a cheque",
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
onTap: () {},
|
||||||
ChequeManagementTile(
|
),
|
||||||
icon: Symbols.front_hand,
|
),
|
||||||
label: AppLocalizations.of(context).stopCheque,
|
Expanded(
|
||||||
onTap: () {},
|
child: ChequeManagementCardTile(
|
||||||
),
|
icon: Symbols.payments,
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
label: "Track Cheque Status",
|
||||||
ChequeManagementTile(
|
subtitle: "Check the current status of your cheque",
|
||||||
icon: Symbols.cancel_presentation,
|
onTap: () {
|
||||||
label: AppLocalizations.of(context).revokeStop,
|
Navigator.push(
|
||||||
onTap: () {},
|
context,
|
||||||
),
|
MaterialPageRoute(
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
builder: (context) => ChequeStatusScreen(
|
||||||
ChequeManagementTile(
|
users: users,
|
||||||
icon: Symbols.payments,
|
selectedIndex: selectedAccountIndex,
|
||||||
label: AppLocalizations.of(context).positivePay,
|
),
|
||||||
onTap: () {},
|
),
|
||||||
),
|
);
|
||||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
},
|
||||||
],
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
child: Center(
|
child: Center(
|
||||||
@@ -89,25 +101,78 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChequeManagementTile extends StatelessWidget {
|
class ChequeManagementCardTile extends StatelessWidget {
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final String label;
|
final String label;
|
||||||
|
final String? subtitle;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
final bool disable;
|
||||||
|
|
||||||
const ChequeManagementTile({
|
const ChequeManagementCardTile({
|
||||||
super.key,
|
super.key,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.label,
|
required this.label,
|
||||||
|
this.subtitle,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
|
this.disable = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListTile(
|
final theme = Theme.of(context);
|
||||||
leading: Icon(icon),
|
return Card(
|
||||||
title: Text(label),
|
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
shape: RoundedRectangleBorder(
|
||||||
onTap: onTap,
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
),
|
||||||
|
elevation: 4, // Add some elevation for better visual separation
|
||||||
|
child: InkWell(
|
||||||
|
onTap:
|
||||||
|
disable ? null : onTap, // Disable InkWell if the tile is disabled
|
||||||
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
||||||
|
child: Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
icon,
|
||||||
|
size: 48, // Make icon larger
|
||||||
|
color:
|
||||||
|
disable ? theme.disabledColor : theme.colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: disable
|
||||||
|
? theme.disabledColor
|
||||||
|
: theme.colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (subtitle != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
subtitle!,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
|
color: disable
|
||||||
|
? theme.disabledColor
|
||||||
|
: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
333
lib/features/cheque/screens/cheque_status_screen.dart
Normal file
333
lib/features/cheque/screens/cheque_status_screen.dart
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:kmobile/api/services/cheque_service.dart';
|
||||||
|
import 'package:kmobile/data/models/user.dart';
|
||||||
|
import 'package:kmobile/di/injection.dart';
|
||||||
|
|
||||||
|
class ChequeStatusScreen extends StatefulWidget {
|
||||||
|
final List<User> users;
|
||||||
|
final int selectedIndex;
|
||||||
|
const ChequeStatusScreen({
|
||||||
|
super.key,
|
||||||
|
required this.users,
|
||||||
|
required this.selectedIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChequeStatusScreen> createState() => _ChequeStatusScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChequeStatusScreenState extends State<ChequeStatusScreen> {
|
||||||
|
User? _selectedAccount;
|
||||||
|
final TextEditingController _searchController = TextEditingController();
|
||||||
|
var service = getIt<ChequeService>();
|
||||||
|
bool _isLoading = true;
|
||||||
|
List<Cheque> _allCheques = [];
|
||||||
|
Map<String, List<Cheque>> _groupedCheques = {};
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
final List<User> _filteredUsers = widget.users
|
||||||
|
.where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (widget.users.isNotEmpty && widget.selectedIndex < widget.users.length) {
|
||||||
|
if (_filteredUsers.isNotEmpty) {
|
||||||
|
if (_filteredUsers.contains(widget.users[widget.selectedIndex])) {
|
||||||
|
_selectedAccount = widget.users[widget.selectedIndex];
|
||||||
|
} else {
|
||||||
|
_selectedAccount = _filteredUsers.first;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_selectedAccount = widget.users[widget.selectedIndex];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_filteredUsers.isNotEmpty) {
|
||||||
|
_selectedAccount = _filteredUsers.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadCheques();
|
||||||
|
_searchController.addListener(() {
|
||||||
|
_filterCheques(_searchController.text);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadCheques() async {
|
||||||
|
if (_selectedAccount == null) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
_groupedCheques = {};
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
String instrType;
|
||||||
|
switch (_selectedAccount!.accountType) {
|
||||||
|
case 'SA':
|
||||||
|
case 'SB':
|
||||||
|
instrType = '10';
|
||||||
|
break;
|
||||||
|
case 'CA':
|
||||||
|
instrType = '11';
|
||||||
|
break;
|
||||||
|
case 'CC':
|
||||||
|
instrType = '13';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
instrType = '10';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final data = await service.ChequeEnquiry(
|
||||||
|
accountNumber: _selectedAccount!.accountNo!, instrType: instrType);
|
||||||
|
_allCheques = data;
|
||||||
|
_groupedCheques.clear();
|
||||||
|
for (var cheque in _allCheques) {
|
||||||
|
if (cheque.type != null) {
|
||||||
|
if (!_groupedCheques.containsKey(cheque.type)) {
|
||||||
|
_groupedCheques[cheque.type!] = [];
|
||||||
|
}
|
||||||
|
_groupedCheques[cheque.type!]!.add(cheque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
_groupedCheques = {};
|
||||||
|
});
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Failed to fetch cheque status: ${e.toString()}'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filterCheques(String query) {
|
||||||
|
_groupedCheques.clear();
|
||||||
|
List<Cheque> filteredCheques;
|
||||||
|
if (query.isEmpty) {
|
||||||
|
filteredCheques = _allCheques;
|
||||||
|
} else {
|
||||||
|
filteredCheques = _allCheques.where((cheque) {
|
||||||
|
final lowerQuery = query.toLowerCase();
|
||||||
|
return (cheque.ChequeNumber?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(cheque.amount?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(cheque.status?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(cheque.fromCheque?.toLowerCase().contains(lowerQuery) ?? false) ||
|
||||||
|
(cheque.toCheque?.toLowerCase().contains(lowerQuery) ?? false);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var cheque in filteredCheques) {
|
||||||
|
if (cheque.type != null) {
|
||||||
|
if (!_groupedCheques.containsKey(cheque.type)) {
|
||||||
|
_groupedCheques[cheque.type!] = [];
|
||||||
|
}
|
||||||
|
_groupedCheques[cheque.type!]!.add(cheque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Track Cheque Status'),
|
||||||
|
centerTitle: false,
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
elevation: 4,
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"Account Number",
|
||||||
|
style:
|
||||||
|
TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
|
),
|
||||||
|
if (_selectedAccount != null)
|
||||||
|
DropdownButtonFormField<User>(
|
||||||
|
value: _selectedAccount,
|
||||||
|
onChanged: (User? newUser) {
|
||||||
|
if (newUser != null) {
|
||||||
|
setState(() {
|
||||||
|
_selectedAccount = newUser;
|
||||||
|
_loadCheques();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
items: widget.users
|
||||||
|
.where((user) =>
|
||||||
|
['SA', 'SB', 'CA', 'CC'].contains(user.accountType))
|
||||||
|
.map((user) {
|
||||||
|
return DropdownMenuItem<User>(
|
||||||
|
value: user,
|
||||||
|
child: Text(user.accountNo.toString()),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const Text('No accounts found'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
TextField(
|
||||||
|
controller: _searchController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Search...',
|
||||||
|
prefixIcon: Icon(Icons.search),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Expanded(
|
||||||
|
child: _isLoading
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: _groupedCheques.isEmpty
|
||||||
|
? const Center(child: Text('No cheque status found.'))
|
||||||
|
: ListView(
|
||||||
|
children: _groupedCheques.entries.map((entry) {
|
||||||
|
return ExpansionTile(
|
||||||
|
title: Text(entry.key, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
children: entry.value
|
||||||
|
.map((cheque) => ChequeStatusTile(cheque: cheque))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChequeStatusTile extends StatelessWidget {
|
||||||
|
final Cheque cheque;
|
||||||
|
|
||||||
|
const ChequeStatusTile({
|
||||||
|
super.key,
|
||||||
|
required this.cheque,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
switch (cheque.type) {
|
||||||
|
case 'CI':
|
||||||
|
return _buildCiTile(context);
|
||||||
|
case 'PR':
|
||||||
|
return _buildPrTile(context);
|
||||||
|
case 'ST':
|
||||||
|
return _buildStTile(context);
|
||||||
|
default:
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCiTile(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildInfoRow('Branch Code:', cheque.branchCode),
|
||||||
|
_buildInfoRow('From Cheque:', cheque.fromCheque),
|
||||||
|
_buildInfoRow('To Cheque:', cheque.toCheque),
|
||||||
|
_buildInfoRow('Date:', cheque.Date),
|
||||||
|
_buildInfoRow('Cheques Count:', cheque.Chequescount),
|
||||||
|
_buildInfoRow('Instrument Type:', cheque.InstrType),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPrTile(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildInfoRow('Branch Code:', cheque.branchCode),
|
||||||
|
_buildInfoRow('Cheque Number:', cheque.ChequeNumber),
|
||||||
|
_buildInfoRow('Date:', cheque.Date),
|
||||||
|
_buildInfoRow('Transaction Code:', cheque.transactionCode),
|
||||||
|
_buildInfoRow('Amount:', cheque.amount),
|
||||||
|
_buildInfoRow('Status:', cheque.status, statusColor: _getStatusColor(cheque.status ?? '')),
|
||||||
|
_buildInfoRow('Instrument Type:', cheque.InstrType),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStTile(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildInfoRow('Branch Code:', cheque.branchCode),
|
||||||
|
_buildInfoRow('From Cheque:', cheque.fromCheque),
|
||||||
|
_buildInfoRow('To Cheque:', cheque.toCheque),
|
||||||
|
_buildInfoRow('Stop Issue Date:', cheque.stopIssueDate),
|
||||||
|
_buildInfoRow('Stop Expiry Date:', cheque.StopExpiryDate),
|
||||||
|
_buildInfoRow('Cheques Count:', cheque.Chequescount),
|
||||||
|
_buildInfoRow('Instrument Type:', cheque.InstrType),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInfoRow(String label, String? value, {Color? statusColor}) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text(value ?? '', style: TextStyle(color: statusColor)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _getStatusColor(String status) {
|
||||||
|
switch (status.toLowerCase()) {
|
||||||
|
case 'cashed':
|
||||||
|
return Colors.green;
|
||||||
|
case 'pending':
|
||||||
|
return Colors.orange;
|
||||||
|
case 'bounced':
|
||||||
|
return Colors.red;
|
||||||
|
default:
|
||||||
|
return Colors.grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import 'package:kmobile/features/accounts/screens/account_statement_screen.dart'
|
|||||||
import 'package:kmobile/features/accounts/screens/all_accounts_screen.dart';
|
import 'package:kmobile/features/accounts/screens/all_accounts_screen.dart';
|
||||||
import 'package:kmobile/features/auth/controllers/auth_cubit.dart';
|
import 'package:kmobile/features/auth/controllers/auth_cubit.dart';
|
||||||
import 'package:kmobile/features/auth/controllers/auth_state.dart';
|
import 'package:kmobile/features/auth/controllers/auth_state.dart';
|
||||||
|
import 'package:kmobile/features/cheque/screens/cheque_management_screen.dart';
|
||||||
import 'package:kmobile/features/customer_info/screens/customer_info_screen.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/beneficiaries/screens/manage_beneficiaries_screen.dart';
|
||||||
import 'package:kmobile/features/enquiry/screens/enquiry_screen.dart';
|
import 'package:kmobile/features/enquiry/screens/enquiry_screen.dart';
|
||||||
@@ -443,7 +444,8 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
final accountType = currAccount.accountType?.toLowerCase();
|
final accountType = currAccount.accountType?.toLowerCase();
|
||||||
final isPaymentDisabled = accountType != 'sa' &&
|
final isPaymentDisabled = accountType != 'sa' &&
|
||||||
accountType != 'sb' &&
|
accountType != 'sb' &&
|
||||||
accountType != 'ca';
|
accountType != 'ca' &&
|
||||||
|
accountType != 'cc';
|
||||||
// first‐time load
|
// first‐time load
|
||||||
if (!_txInitialized) {
|
if (!_txInitialized) {
|
||||||
_txInitialized = true;
|
_txInitialized = true;
|
||||||
@@ -643,20 +645,20 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
const EnquiryScreen()));
|
const EnquiryScreen()));
|
||||||
}),
|
}),
|
||||||
_buildQuickLink(
|
_buildQuickLink(
|
||||||
Symbols.person,
|
Symbols.checkbook,
|
||||||
AppLocalizations.of(context).profile,
|
AppLocalizations.of(context).chequeManagement,
|
||||||
() {
|
() {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => ProfileScreen(
|
builder: (context) => ChequeManagementScreen(
|
||||||
mobileNumber: mobileNumberToPass,
|
users: users,
|
||||||
customerNo: customerNo,
|
selectedIndex: selectedAccountIndex
|
||||||
customerName: customerName),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
disable: false,
|
disable: isPaymentDisabled,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user