import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; /// Monthly payment schedule table /// Shows month-wise breakdown of payments and chit win amounts class MonthlyScheduleTable extends StatelessWidget { final double totalValue; final int durationMonths; final double monthlyInstallment; final double commission; final double maxDividend; const MonthlyScheduleTable({ super.key, required this.totalValue, required this.durationMonths, required this.monthlyInstallment, required this.commission, required this.maxDividend, }); @override Widget build(BuildContext context) { if (totalValue <= 0 || durationMonths <= 0) { return _buildEmptyState(); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header _buildHeader(), SizedBox(height: 12.h), // Month list Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(12.r), ), constraints: BoxConstraints( maxHeight: 350.h, // Scrollable if too many months ), child: ClipRRect( borderRadius: BorderRadius.circular(12.r), child: ListView.builder( shrinkWrap: true, padding: EdgeInsets.zero, itemCount: durationMonths, itemBuilder: (context, index) { return _buildMonthRow(index + 1); }, ), ), ), SizedBox(height: 12.h), // Summary footer _buildSummaryFooter(), ], ); } Widget _buildHeader() { return Row( children: [ Icon(Icons.calendar_month_rounded, color: Colors.green.shade600, size: 20.w), SizedBox(width: 8.w), Text( 'Month-wise Payment Schedule', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), const Spacer(), Container( padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h), decoration: BoxDecoration( color: Colors.green.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all(color: Colors.green.shade300), ), child: Text( '$durationMonths Months', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: Colors.green.shade700, ), ), ), ], ); } Widget _buildMonthRow(int month) { final subscriptionAmount = totalValue / durationMonths; final chitWinAmount = _calculateChitWinAmount(month); final isEarlyMonth = month <= (durationMonths * 0.3).ceil(); final isLastMonth = month == durationMonths; return Container( decoration: BoxDecoration( color: isLastMonth ? Colors.purple.shade50 : isEarlyMonth ? Colors.green.shade50 : Colors.white, border: Border( bottom: BorderSide( color: Colors.grey.shade200, width: 1, ), ), ), child: IntrinsicHeight( child: Row( children: [ // Month number Container( width: 55.w, padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.w), decoration: BoxDecoration( color: isLastMonth ? Colors.purple.shade100 : isEarlyMonth ? Colors.green.shade100 : Colors.grey.shade100, border: Border( right: BorderSide( color: Colors.grey.shade300, width: 1, ), ), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'M', style: TextStyle( fontSize: 9.sp, color: Colors.grey.shade600, ), ), Text( '$month', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: isLastMonth ? Colors.purple.shade700 : isEarlyMonth ? Colors.green.shade700 : Colors.grey.shade800, ), ), ], ), ), // Payment details Expanded( child: Padding( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ // Payment amount Row( children: [ Expanded( flex: 3, child: Text( 'Payment:', style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), ), ), Expanded( flex: 2, child: Text( '₹${monthlyInstallment.toStringAsFixed(0)}', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), textAlign: TextAlign.right, ), ), ], ), SizedBox(height: 4.h), // Chit win amount Row( children: [ Icon( Icons.emoji_events_rounded, size: 12.w, color: Colors.amber.shade700, ), SizedBox(width: 4.w), Expanded( flex: 3, child: Text( 'Win:', style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), ), Expanded( flex: 2, child: Text( '₹${chitWinAmount.toStringAsFixed(0)}', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.bold, color: Colors.green.shade700, ), textAlign: TextAlign.right, ), ), ], ), // Show special badge for first and last month if (isEarlyMonth || isLastMonth) ...[ SizedBox(height: 4.h), Container( padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 2.h), decoration: BoxDecoration( color: isLastMonth ? Colors.purple.shade200 : Colors.green.shade200, borderRadius: BorderRadius.circular(6.r), ), child: Text( isLastMonth ? 'Last' : 'Early Adv.', style: TextStyle( fontSize: 9.sp, fontWeight: FontWeight.w600, color: isLastMonth ? Colors.purple.shade900 : Colors.green.shade900, ), overflow: TextOverflow.ellipsis, ), ), ], ], ), ), ), ], ), ), ); } double _calculateChitWinAmount(int month) { // Calculate chit win amount based on month // Formula: Total Value - Total Commission // This is the pool amount that winner receives final totalCommission = commission * durationMonths; final chitWinAmount = totalValue - totalCommission; // Winner receives the full chit value minus commission return chitWinAmount; } Widget _buildEmptyState() { return Container( padding: EdgeInsets.all(20.w), decoration: BoxDecoration( color: Colors.orange.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all(color: Colors.orange.shade200), ), child: Row( children: [ Icon(Icons.info_outline, color: Colors.orange.shade600, size: 24.w), SizedBox(width: 12.w), Expanded( child: Text( 'Enter chitfund details above to see the month-wise payment schedule', style: TextStyle( fontSize: 14.sp, color: Colors.orange.shade700, ), ), ), ], ), ); } Widget _buildSummaryFooter() { final totalCollection = monthlyInstallment * durationMonths; final totalCommission = commission * durationMonths; final netDistribution = totalValue; return Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all(color: Colors.blue.shade200), ), child: Column( children: [ Row( children: [ Icon(Icons.summarize_rounded, color: Colors.blue.shade700, size: 16.w), SizedBox(width: 6.w), Text( 'Summary', style: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.bold, color: Colors.blue.shade800, ), ), ], ), SizedBox(height: 10.h), _buildSummaryRow('Total Collected', '₹${totalCollection.toStringAsFixed(0)}'), _buildSummaryRow('Commission', '₹${totalCommission.toStringAsFixed(0)}'), _buildSummaryRow('Distributed', '₹${netDistribution.toStringAsFixed(0)}'), Divider(height: 12.h, color: Colors.blue.shade300), _buildSummaryRow( 'Per Month', '₹${subscriptionAmount.toStringAsFixed(0)}', isHighlight: true, ), ], ), ); } double get subscriptionAmount => totalValue / durationMonths; Widget _buildSummaryRow(String label, String value, {bool isHighlight = false}) { return Padding( padding: EdgeInsets.symmetric(vertical: 3.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 3, child: Text( label, style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade700, fontWeight: isHighlight ? FontWeight.w600 : FontWeight.normal, ), overflow: TextOverflow.ellipsis, ), ), Expanded( flex: 2, child: Text( value, style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: isHighlight ? Colors.blue.shade800 : Colors.grey.shade800, ), textAlign: TextAlign.right, overflow: TextOverflow.ellipsis, ), ), ], ), ); } } /// Expandable monthly schedule widget class ExpandableMonthlySchedule extends StatefulWidget { final double totalValue; final int durationMonths; final double monthlyInstallment; final double commission; final double maxDividend; const ExpandableMonthlySchedule({ super.key, required this.totalValue, required this.durationMonths, required this.monthlyInstallment, required this.commission, required this.maxDividend, }); @override State createState() => _ExpandableMonthlyScheduleState(); } class _ExpandableMonthlyScheduleState extends State { bool _isExpanded = false; @override Widget build(BuildContext context) { return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), child: Column( children: [ // Header (always visible) InkWell( onTap: () { if (widget.totalValue > 0 && widget.durationMonths > 0) { setState(() => _isExpanded = !_isExpanded); } }, borderRadius: BorderRadius.circular(12.r), child: Padding( padding: EdgeInsets.all(16.w), child: Row( children: [ Container( padding: EdgeInsets.all(10.w), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(10.r), ), child: Icon( Icons.event_note_rounded, color: Colors.blue.shade600, size: 24.w, ), ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Monthly Payment Schedule', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), SizedBox(height: 2.h), Text( widget.totalValue > 0 && widget.durationMonths > 0 ? 'Tap to ${_isExpanded ? 'hide' : 'view'} all ${widget.durationMonths} months' : 'Enter details above to preview', style: TextStyle( fontSize: 13.sp, color: Colors.grey.shade600, ), ), ], ), ), if (widget.totalValue > 0 && widget.durationMonths > 0) Icon( _isExpanded ? Icons.expand_less : Icons.expand_more, color: Colors.grey.shade600, size: 24.w, ), ], ), ), ), // Expandable content if (_isExpanded) Padding( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h), child: MonthlyScheduleTable( totalValue: widget.totalValue, durationMonths: widget.durationMonths, monthlyInstallment: widget.monthlyInstallment, commission: widget.commission, maxDividend: widget.maxDividend, ), ), ], ), ); } } /// Compact monthly schedule preview (first 3 and last 2 months) class CompactMonthlySchedule extends StatelessWidget { final double totalValue; final int durationMonths; final double monthlyInstallment; final double commission; const CompactMonthlySchedule({ super.key, required this.totalValue, required this.durationMonths, required this.monthlyInstallment, required this.commission, }); @override Widget build(BuildContext context) { if (totalValue <= 0 || durationMonths <= 0) { return const SizedBox.shrink(); } final subscriptionAmount = totalValue / durationMonths; final chitWinBase = totalValue - (commission * durationMonths); return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all(color: Colors.grey.shade200), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Payment Schedule Preview', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), SizedBox(height: 12.h), // Table header Row( children: [ SizedBox( width: 60.w, child: Text( 'Month', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade700, ), ), ), Expanded( child: Text( 'Payment', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade700, ), textAlign: TextAlign.right, ), ), SizedBox(width: 12.w), Expanded( child: Text( 'Win Amount', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade700, ), textAlign: TextAlign.right, ), ), ], ), Divider(height: 12.h, color: Colors.grey.shade300), // Show first 3 months ..._buildCompactRows([1, 2, 3], subscriptionAmount, chitWinBase), // Show separator if more months if (durationMonths > 5) ...[ Padding( padding: EdgeInsets.symmetric(vertical: 8.h), child: Center( child: Text( '... ${durationMonths - 5} more months ...', style: TextStyle( fontSize: 11.sp, color: Colors.grey.shade500, fontStyle: FontStyle.italic, ), ), ), ), ], // Show last 2 months if (durationMonths > 3) ..._buildCompactRows( [durationMonths - 1, durationMonths], subscriptionAmount, chitWinBase, ), ], ), ); } List _buildCompactRows(List months, double subscription, double chitWinAmount) { return months.map((month) { if (month > durationMonths) return const SizedBox.shrink(); return Padding( padding: EdgeInsets.symmetric(vertical: 4.h), child: Row( children: [ SizedBox( width: 60.w, child: Text( '$month', style: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), ), Expanded( child: Text( '₹${monthlyInstallment.toStringAsFixed(0)}', style: TextStyle( fontSize: 13.sp, color: Colors.grey.shade700, ), textAlign: TextAlign.right, ), ), SizedBox(width: 12.w), Expanded( child: Text( '₹${chitWinAmount.toStringAsFixed(0)}', style: TextStyle( fontSize: 13.sp, fontWeight: FontWeight.w600, color: Colors.green.shade700, ), textAlign: TextAlign.right, ), ), ], ), ); }).toList(); } }