484 lines
14 KiB
Dart
484 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import '../../core/models/chit_group.dart';
|
|
|
|
class MonthlyPaymentStatusPage extends StatefulWidget {
|
|
final ChitGroup chitfund;
|
|
final int month;
|
|
final int year;
|
|
|
|
const MonthlyPaymentStatusPage({
|
|
Key? key,
|
|
required this.chitfund,
|
|
required this.month,
|
|
required this.year,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<MonthlyPaymentStatusPage> createState() => _MonthlyPaymentStatusPageState();
|
|
}
|
|
|
|
class _MonthlyPaymentStatusPageState extends State<MonthlyPaymentStatusPage> {
|
|
List<Map<String, dynamic>> _paymentData = [];
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadPaymentData();
|
|
}
|
|
|
|
void _loadPaymentData() {
|
|
// Simulate loading payment data
|
|
Future.delayed(const Duration(milliseconds: 500), () {
|
|
setState(() {
|
|
_paymentData = _generatePaymentData();
|
|
_isLoading = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.grey.shade50,
|
|
appBar: AppBar(
|
|
title: Text(
|
|
'Payment Status - ${_getMonthName(widget.month)}/${widget.year}',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
backgroundColor: Colors.green.shade600,
|
|
foregroundColor: Colors.white,
|
|
elevation: 2,
|
|
actions: [
|
|
IconButton(
|
|
icon: Icon(Icons.refresh, size: 24.w),
|
|
onPressed: _loadPaymentData,
|
|
tooltip: 'Refresh',
|
|
),
|
|
],
|
|
),
|
|
body: _isLoading
|
|
? Center(
|
|
child: CircularProgressIndicator(
|
|
color: Colors.green.shade600,
|
|
),
|
|
)
|
|
: SingleChildScrollView(
|
|
padding: EdgeInsets.all(16.w),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Header with Sai Baba icon
|
|
_buildHeader(),
|
|
SizedBox(height: 24.h),
|
|
|
|
// Payment Status Table
|
|
_buildPaymentTable(),
|
|
SizedBox(height: 24.h),
|
|
|
|
// Summary Statistics
|
|
_buildSummaryStats(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildHeader() {
|
|
return Container(
|
|
padding: EdgeInsets.all(20.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 8.r,
|
|
offset: Offset(0, 2.h),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: [
|
|
// Sai Baba Icon
|
|
Container(
|
|
width: 60.w,
|
|
height: 60.h,
|
|
decoration: BoxDecoration(
|
|
color: Colors.orange.shade100,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
Icons.person,
|
|
size: 30.w,
|
|
color: Colors.orange.shade600,
|
|
),
|
|
),
|
|
SizedBox(width: 16.w),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'No ${_getMonthNumber()} ${_getMonthName(widget.month)}/${widget.year}',
|
|
style: TextStyle(
|
|
fontSize: 20.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
),
|
|
SizedBox(height: 4.h),
|
|
Text(
|
|
'Chit Installment Payment Status',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey.shade600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPaymentTable() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 8.r,
|
|
offset: Offset(0, 2.h),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
children: [
|
|
// Table Header
|
|
Container(
|
|
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.green.shade600,
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(12.r),
|
|
topRight: Radius.circular(12.r),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
flex: 1,
|
|
child: Text(
|
|
'Sl No',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 3,
|
|
child: Text(
|
|
'Name',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
'Chit Install Amount (₹)',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
'Paid/Not',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Table Rows
|
|
..._paymentData.map((data) {
|
|
|
|
return Container(
|
|
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 12.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.yellow.shade50,
|
|
border: Border(
|
|
bottom: BorderSide(
|
|
color: Colors.grey.shade200,
|
|
width: 0.5,
|
|
),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
flex: 1,
|
|
child: Text(
|
|
data['slNo'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.normal,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 3,
|
|
child: Text(
|
|
data['name'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.normal,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
data['amount'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.normal,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(vertical: 4.h, horizontal: 8.w),
|
|
decoration: BoxDecoration(
|
|
color: data['isPaid'] ? Colors.green.shade100 : Colors.red.shade100,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
border: Border.all(
|
|
color: data['isPaid'] ? Colors.green.shade300 : Colors.red.shade300,
|
|
),
|
|
),
|
|
child: Text(
|
|
data['status'],
|
|
style: TextStyle(
|
|
fontSize: 11.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: data['isPaid'] ? Colors.green.shade700 : Colors.red.shade700,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}).toList(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSummaryStats() {
|
|
final paidCount = _paymentData.where((data) => data['isPaid']).length;
|
|
final totalCount = _paymentData.length;
|
|
final paidPercentage = (paidCount / totalCount * 100).round();
|
|
|
|
return Container(
|
|
padding: EdgeInsets.all(20.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 8.r,
|
|
offset: Offset(0, 2.h),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Payment Summary',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
),
|
|
SizedBox(height: 16.h),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: _buildStatCard(
|
|
'Total Members',
|
|
'$totalCount',
|
|
Icons.group,
|
|
Colors.blue,
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: _buildStatCard(
|
|
'Paid',
|
|
'$paidCount',
|
|
Icons.check_circle,
|
|
Colors.green,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 12.h),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: _buildStatCard(
|
|
'Pending',
|
|
'${totalCount - paidCount}',
|
|
Icons.pending,
|
|
Colors.orange,
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: _buildStatCard(
|
|
'Completion',
|
|
'$paidPercentage%',
|
|
Icons.percent,
|
|
Colors.purple,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildStatCard(String title, String value, IconData icon, Color color) {
|
|
return Container(
|
|
padding: EdgeInsets.all(16.w),
|
|
decoration: BoxDecoration(
|
|
color: color.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
border: Border.all(color: color.withOpacity(0.3)),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Icon(icon, color: color, size: 24.w),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color: Colors.grey.shade600,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
SizedBox(height: 4.h),
|
|
Text(
|
|
value,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: color,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
List<Map<String, dynamic>> _generatePaymentData() {
|
|
// Generate sample payment data based on chitfund members
|
|
final List<Map<String, dynamic>> paymentData = [];
|
|
final installmentAmount = widget.chitfund.monthlyInstallment;
|
|
|
|
// Sample member names (you can replace with actual member data)
|
|
final memberNames = [
|
|
'R Rama Krishna Reddy',
|
|
'K Srinivas Reddy',
|
|
'Ch Ramchandra Reddy',
|
|
'B Krishnahari 1',
|
|
'B Krishnahari 2',
|
|
'N Paranjyothi 1',
|
|
'N Paranjyothi 2',
|
|
'Sharada 1',
|
|
'Sharada 2',
|
|
'Ibrahim',
|
|
'Waheeda Bee',
|
|
'R Janardhan Reddy',
|
|
'Shashank 1',
|
|
'Shashank 2',
|
|
'S Saritha',
|
|
'S Rakesh Reddy',
|
|
'S Rohini (Sony)',
|
|
'K Shalini',
|
|
'K Sundeep Reddy',
|
|
'K Thirupathi Reddy',
|
|
];
|
|
|
|
for (int i = 0; i < memberNames.length; i++) {
|
|
final isPaid = i < 15; // First 15 members are paid, rest are pending
|
|
paymentData.add({
|
|
'slNo': '${i + 1}',
|
|
'name': memberNames[i],
|
|
'amount': installmentAmount.toStringAsFixed(0),
|
|
'status': isPaid ? 'Paid' : 'Not Paid',
|
|
'isPaid': isPaid,
|
|
});
|
|
}
|
|
|
|
return paymentData;
|
|
}
|
|
|
|
String _getMonthName(int month) {
|
|
final months = [
|
|
'January', 'February', 'March', 'April', 'May', 'June',
|
|
'July', 'August', 'September', 'October', 'November', 'December'
|
|
];
|
|
return months[month - 1];
|
|
}
|
|
|
|
int _getMonthNumber() {
|
|
// Calculate which month number this is since chitfund started
|
|
final startDate = widget.chitfund.startDate;
|
|
final currentDate = DateTime(widget.year, widget.month);
|
|
final monthsDiff = (currentDate.year - startDate!.year) * 12 + (currentDate.month - startDate!.month);
|
|
return monthsDiff + 1;
|
|
}
|
|
}
|