chequemanagement #1
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user