490 lines
15 KiB
Dart
490 lines
15 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import '../../core/models/chit_group.dart';
|
|
|
|
class ChitfundSchedulePage extends StatefulWidget {
|
|
final ChitGroup chitfund;
|
|
|
|
const ChitfundSchedulePage({
|
|
Key? key,
|
|
required this.chitfund,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<ChitfundSchedulePage> createState() => _ChitfundSchedulePageState();
|
|
}
|
|
|
|
class _ChitfundSchedulePageState extends State<ChitfundSchedulePage> {
|
|
|
|
String _formatIndianCurrency(double amount) {
|
|
// Convert to integer to avoid decimal places
|
|
int intAmount = amount.round();
|
|
|
|
// Format with Indian numbering system (commas every 2 digits after the first 3)
|
|
String amountStr = intAmount.toString();
|
|
String formatted = '';
|
|
|
|
if (amountStr.length <= 3) {
|
|
formatted = amountStr;
|
|
} else {
|
|
// For amounts > 999, use Indian comma system
|
|
int remaining = amountStr.length;
|
|
int start = 0;
|
|
|
|
// First group (rightmost 3 digits)
|
|
if (remaining > 3) {
|
|
formatted = amountStr.substring(amountStr.length - 3);
|
|
remaining -= 3;
|
|
start = amountStr.length - 3;
|
|
} else {
|
|
formatted = amountStr;
|
|
remaining = 0;
|
|
}
|
|
|
|
// Subsequent groups (2 digits each)
|
|
while (remaining > 0) {
|
|
int groupSize = remaining >= 2 ? 2 : remaining;
|
|
int groupStart = start - groupSize;
|
|
String group = amountStr.substring(groupStart, start);
|
|
formatted = group + ',' + formatted;
|
|
start = groupStart;
|
|
remaining -= groupSize;
|
|
}
|
|
}
|
|
|
|
return '₹$formatted';
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.grey.shade50,
|
|
appBar: AppBar(
|
|
title: Text(
|
|
'${widget.chitfund.name} - Schedule',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
backgroundColor: Colors.green.shade600,
|
|
foregroundColor: Colors.white,
|
|
elevation: 2,
|
|
),
|
|
body: SingleChildScrollView(
|
|
padding: EdgeInsets.all(16.w),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Header with Sai Baba icon
|
|
_buildHeader(),
|
|
SizedBox(height: 24.h),
|
|
|
|
// Chitfund Schedule Table
|
|
_buildScheduleTable(),
|
|
SizedBox(height: 24.h),
|
|
|
|
// Summary Information
|
|
_buildSummaryInfo(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
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(
|
|
widget.chitfund.name,
|
|
style: TextStyle(
|
|
fontSize: 24.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
),
|
|
SizedBox(height: 4.h),
|
|
Text(
|
|
'Chitfund Schedule & Payment Details',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: Colors.grey.shade600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildScheduleTable() {
|
|
final scheduleData = _generateScheduleData();
|
|
|
|
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: 2,
|
|
child: Text(
|
|
'Month',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
'Chit Value',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
'Bid Amount',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 14.sp,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// Table Rows
|
|
...scheduleData.asMap().entries.map((entry) {
|
|
final index = entry.key;
|
|
final data = entry.value;
|
|
final isTotalRow = data['isTotal'] == true;
|
|
|
|
return Container(
|
|
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 12.w),
|
|
decoration: BoxDecoration(
|
|
color: isTotalRow
|
|
? Colors.orange.shade50
|
|
: _getRowColor(index, scheduleData.length - 1),
|
|
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: isTotalRow ? FontWeight.bold : FontWeight.normal,
|
|
color: isTotalRow ? Colors.orange.shade800 : Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
data['month'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: isTotalRow ? FontWeight.bold : FontWeight.normal,
|
|
color: isTotalRow ? Colors.orange.shade800 : Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
data['chitValue'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: isTotalRow ? FontWeight.bold : FontWeight.normal,
|
|
color: isTotalRow ? Colors.orange.shade800 : Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 2,
|
|
child: Text(
|
|
data['bidAmount'],
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: isTotalRow ? FontWeight.bold : FontWeight.normal,
|
|
color: isTotalRow ? Colors.orange.shade800 : Colors.grey.shade800,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}).toList(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSummaryInfo() {
|
|
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(
|
|
'Chitfund Summary',
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
),
|
|
SizedBox(height: 16.h),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: _buildSummaryCard(
|
|
'Total Value',
|
|
_formatIndianCurrency(widget.chitfund.totalValue),
|
|
Icons.account_balance_wallet,
|
|
Colors.blue,
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: _buildSummaryCard(
|
|
'Monthly Installment',
|
|
_formatIndianCurrency(widget.chitfund.monthlyInstallment),
|
|
Icons.payment,
|
|
Colors.green,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 12.h),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: _buildSummaryCard(
|
|
'Duration',
|
|
'${widget.chitfund.durationMonths} months',
|
|
Icons.calendar_today,
|
|
Colors.orange,
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: _buildSummaryCard(
|
|
'Max Members',
|
|
'${widget.chitfund.maxMembers}',
|
|
Icons.group,
|
|
Colors.purple,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSummaryCard(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: 14.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: color,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
List<Map<String, dynamic>> _generateScheduleData() {
|
|
final List<Map<String, dynamic>> scheduleData = [];
|
|
final startDate = widget.chitfund.startDate;
|
|
final totalMonths = widget.chitfund.durationMonths;
|
|
final chitValue = widget.chitfund.totalValue;
|
|
|
|
// Return empty data if startDate is null
|
|
if (startDate == null) {
|
|
return scheduleData;
|
|
}
|
|
|
|
// Calculate bid amounts (starting at 87.65% of chit value and increasing by 2,600 each month)
|
|
final bidIncrement = 2600;
|
|
var currentBidAmount = chitValue * 0.8765; // Starting at 87.65% of chit value (same as financial tab)
|
|
|
|
for (int i = 0; i < totalMonths; i++) {
|
|
final monthDate = DateTime(startDate.year, startDate.month + i);
|
|
final monthName = _getMonthName(monthDate);
|
|
|
|
scheduleData.add({
|
|
'slNo': '${i + 1}',
|
|
'month': monthName,
|
|
'chitValue': _formatIndianCurrency(chitValue),
|
|
'bidAmount': _formatIndianCurrency(currentBidAmount),
|
|
'isTotal': false,
|
|
});
|
|
|
|
currentBidAmount += bidIncrement;
|
|
}
|
|
|
|
// Add total row
|
|
final totalChitValue = chitValue * totalMonths;
|
|
final totalBidAmount = scheduleData.fold(0.0, (sum, entry) {
|
|
if (entry['isTotal'] == true) return sum;
|
|
final bidAmountStr = entry['bidAmount'].toString().replaceAll('₹', '').replaceAll(',', '');
|
|
return sum + double.parse(bidAmountStr);
|
|
});
|
|
|
|
scheduleData.add({
|
|
'slNo': 'Total',
|
|
'month': '',
|
|
'chitValue': _formatIndianCurrency(totalChitValue),
|
|
'bidAmount': _formatIndianCurrency(totalBidAmount),
|
|
'isTotal': true,
|
|
});
|
|
|
|
return scheduleData;
|
|
}
|
|
|
|
String _getMonthName(DateTime date) {
|
|
final months = [
|
|
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
|
|
];
|
|
return '${months[date.month - 1]}-${date.year.toString().substring(2)}';
|
|
}
|
|
|
|
Color _getRowColor(int index, int totalRows) {
|
|
if (index < 6) {
|
|
return Colors.orange.shade50; // Light orange for first 6 rows
|
|
} else if (index == 6) {
|
|
return Colors.white; // White for 7th row
|
|
} else {
|
|
return Colors.green.shade50; // Light green for remaining rows
|
|
}
|
|
}
|
|
|
|
}
|