Files
kmobile/lib/features/cheque/screens/cheque_status_screen.dart
2025-12-24 18:06:12 +05:30

334 lines
10 KiB
Dart

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;
}
}
}