import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/chit_group_service.dart'; import '../../core/services/payment_service.dart'; import '../../core/services/auth_service.dart'; import '../../core/models/chit_group.dart'; import '../../core/models/payment.dart'; import '../../core/models/monthly_draw.dart'; class MemberGroupDetailsPage extends StatefulWidget { final ChitGroup group; const MemberGroupDetailsPage({ super.key, required this.group, }); @override State createState() => _MemberGroupDetailsPageState(); } class _MemberGroupDetailsPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; final _chitGroupService = Get.find(); final _paymentService = Get.find(); final _authService = Get.find(); @override void initState() { super.initState(); _tabController = TabController(length: 3, vsync: this); // Load data WidgetsBinding.instance.addPostFrameCallback((_) { _loadData(); }); } Future _loadData() async { final groupId = widget.group.id; await Future.wait([ _chitGroupService.loadChitGroupDetails(groupId), _chitGroupService.loadGroupMembers(groupId), _chitGroupService.loadGroupMonthlyDraws(groupId), _paymentService.loadGroupPayments(groupId), ]); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey.shade50, appBar: AppBar( title: Text( widget.group.name, style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.w600), ), backgroundColor: Colors.green.shade600, foregroundColor: Colors.white, elevation: 2, bottom: TabBar( controller: _tabController, indicatorColor: Colors.white, indicatorWeight: 3, labelStyle: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600), unselectedLabelStyle: TextStyle(fontSize: 14.sp), tabs: const [ Tab(text: 'Overview'), Tab(text: 'Payments'), Tab(text: 'Draws'), ], ), ), body: TabBarView( controller: _tabController, children: [ _buildOverviewTab(), _buildPaymentsTab(), _buildDrawsTab(), ], ), ); } Widget _buildOverviewTab() { return Obx(() { final group = _chitGroupService.selectedGroup.value ?? widget.group; final members = _chitGroupService.groupMembers; final myMember = members.firstWhereOrNull( (m) => m.userId == _authService.currentUser.value?.id, ); return RefreshIndicator( onRefresh: _loadData, child: ListView( padding: EdgeInsets.all(16.w), children: [ // Last Draw Winner Card (if exists) if (_chitGroupService.monthlyDraws.isNotEmpty) _buildLastDrawWinnerCard(_chitGroupService.monthlyDraws.first), if (_chitGroupService.monthlyDraws.isNotEmpty) SizedBox(height: 16.h), // Group Info Card (Compact) _buildCompactGroupInfoCard(group), SizedBox(height: 16.h), // My Status Card if (myMember != null) _buildMyStatusCard(myMember), if (myMember != null) SizedBox(height: 16.h), // Quick Stats _buildQuickStats(group, myMember), SizedBox(height: 16.h), // Members Card _buildMembersCard(members), ], ), ); }); } Widget _buildPaymentsTab() { final myUserId = _authService.currentUser.value?.id; return Obx(() { final payments = _paymentService.payments; final isLoading = _paymentService.isLoading; // Filter to show only my payments final myPayments = payments.where((p) => p.userId == myUserId).toList(); if (isLoading) { return Center( child: CircularProgressIndicator(color: Colors.green.shade600), ); } return RefreshIndicator( onRefresh: () => _paymentService.loadGroupPayments(widget.group.id), child: myPayments.isEmpty ? _buildEmptyPayments() : ListView.builder( padding: EdgeInsets.all(16.w), itemCount: myPayments.length, itemBuilder: (context, index) { return _buildPaymentCard(myPayments[index]); }, ), ); }); } Widget _buildDrawsTab() { return Obx(() { final draws = _chitGroupService.monthlyDraws; if (_chitGroupService.isLoading.value) { return Center( child: CircularProgressIndicator(color: Colors.green.shade600), ); } return RefreshIndicator( onRefresh: () => _chitGroupService.loadGroupMonthlyDraws(widget.group.id), child: draws.isEmpty ? _buildEmptyDraws() : ListView.builder( padding: EdgeInsets.all(16.w), itemCount: draws.length, itemBuilder: (context, index) { return _buildDrawCard(draws[index]); }, ), ); }); } Widget _buildLastDrawWinnerCard(MonthlyDraw lastDraw) { final isWinner = lastDraw.winnerId == _authService.currentUser.value?.id; return Card( elevation: 3, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( gradient: LinearGradient( colors: isWinner ? [Colors.amber.shade400, Colors.amber.shade600] : [Colors.purple.shade400, Colors.purple.shade600], ), borderRadius: BorderRadius.circular(16.r), ), child: Column( children: [ Row( children: [ Container( padding: EdgeInsets.all(8.w), decoration: BoxDecoration( color: Colors.white.withOpacity(0.3), borderRadius: BorderRadius.circular(12.r), ), child: Icon( isWinner ? Icons.emoji_events : Icons.casino, color: Colors.white, size: 24.w, ), ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( isWinner ? '🎉 You Won!' : 'Latest Draw Winner', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.white, ), ), Text( 'Month ${lastDraw.month}, ${lastDraw.year}', style: TextStyle( fontSize: 14.sp, color: Colors.white.withOpacity(0.9), ), ), ], ), ), ], ), SizedBox(height: 16.h), Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12.r), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Text( lastDraw.winner?.fullName ?? 'Unknown', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), SizedBox(height: 4.h), Text( 'Winner', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), Container( width: 1, height: 40.h, color: Colors.grey.shade300, ), Column( children: [ Text( '₹${_formatCurrency(lastDraw.prizeAmount)}', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.green.shade700, ), ), SizedBox(height: 4.h), Text( 'Prize', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ], ), ), ], ), ), ); } Widget _buildCompactGroupInfoCard(ChitGroup group) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Padding( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Group Info', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), _buildStatusBadge(group.status), ], ), SizedBox(height: 16.h), Row( children: [ Expanded(child: _buildCompactInfo('Total Value', '₹${_formatCurrency(group.totalValue)}', Icons.account_balance_wallet)), SizedBox(width: 12.w), Expanded(child: _buildCompactInfo('Installment', '₹${_formatCurrency(group.monthlyInstallment)}', Icons.payment)), ], ), SizedBox(height: 12.h), Row( children: [ Expanded(child: _buildCompactInfo('Duration', '${group.durationMonths} months', Icons.calendar_today)), SizedBox(width: 12.w), Expanded(child: _buildCompactInfo('Draw Date', '${group.drawDate}th', Icons.event)), ], ), if (group.startDate != null) ...[ SizedBox(height: 12.h), _buildCompactInfo('Started On', _formatDate(group.startDate!), Icons.play_circle), ], ], ), ), ); } Widget _buildCompactInfo(String label, String value, IconData icon) { return Row( children: [ Icon(icon, size: 18.w, color: Colors.green.shade600), SizedBox(width: 8.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 2.h), Text( value, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), ], ), ), ], ); } Widget _buildMyStatusCard(dynamic member) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Container( padding: EdgeInsets.all(20.w), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.blue.shade50, Colors.blue.shade100], ), borderRadius: BorderRadius.circular(16.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.person, color: Colors.blue.shade700, size: 24.w), SizedBox(width: 12.w), Text( 'My Status', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.blue.shade800, ), ), ], ), SizedBox(height: 16.h), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildStatItem('Total Paid', '₹${_formatCurrency(member.totalPaid)}', Colors.green), Container(width: 1, height: 40.h, color: Colors.blue.shade300), _buildStatItem('Total Won', '₹${_formatCurrency(member.totalWon)}', Colors.orange), ], ), SizedBox(height: 12.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12.r), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Joined', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), Text( _formatDate(member.joinedDate), style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), ], ), ), ], ), ), ); } Widget _buildMembersCard(List members) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.r)), child: Padding( padding: EdgeInsets.all(20.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Members', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), Text( '${members.length} members', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), SizedBox(height: 16.h), ...members.map((member) => _buildMemberItem(member)), ], ), ), ); } Widget _buildMemberItem(dynamic member) { final user = member.user; final isMe = member.userId == _authService.currentUser.value?.id; return Container( margin: EdgeInsets.only(bottom: 12.h), padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: isMe ? Colors.green.shade50 : Colors.grey.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all( color: isMe ? Colors.green.shade300 : Colors.grey.shade200, ), ), child: Row( children: [ CircleAvatar( radius: 20.r, backgroundColor: isMe ? Colors.green.shade600 : Colors.grey.shade400, child: Text( user?.fullName?.substring(0, 1).toUpperCase() ?? 'M', style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.bold, ), ), ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( user?.fullName ?? 'Unknown', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), ), if (isMe) Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), decoration: BoxDecoration( color: Colors.green.shade600, borderRadius: BorderRadius.circular(8.r), ), child: Text( 'You', style: TextStyle( fontSize: 12.sp, color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ], ), SizedBox(height: 4.h), Text( user?.mobileNumber ?? '', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ), ], ), ); } Widget _buildQuickStats(ChitGroup group, dynamic myMember) { return Row( children: [ Expanded( child: _buildQuickStatCard( 'Total Members', '${group.currentMemberCount}', Icons.people, Colors.blue.shade600, ), ), SizedBox(width: 12.w), Expanded( child: _buildQuickStatCard( 'Duration', '${group.durationMonths}M', Icons.calendar_month, Colors.orange.shade600, ), ), ], ); } Widget _buildQuickStatCard(String label, String value, IconData icon, Color color) { return Card( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)), child: Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( gradient: LinearGradient( colors: [color.withOpacity(0.1), color.withOpacity(0.05)], ), borderRadius: BorderRadius.circular(12.r), ), child: Column( children: [ Icon(icon, color: color, size: 28.w), SizedBox(height: 8.h), Text( value, style: TextStyle( fontSize: 24.sp, fontWeight: FontWeight.bold, color: color, ), ), SizedBox(height: 4.h), Text( label, style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), textAlign: TextAlign.center, ), ], ), ), ); } Widget _buildPaymentCard(Payment payment) { return Card( margin: EdgeInsets.only(bottom: 12.h), elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)), child: Padding( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Month ${payment.month}, ${payment.year}', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), _buildPaymentStatusBadge(payment.status), ], ), SizedBox(height: 12.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Amount', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 4.h), Text( '₹${_formatCurrency(payment.amount)}', style: TextStyle( fontSize: 20.sp, fontWeight: FontWeight.bold, color: Colors.green.shade700, ), ), ], ), if (payment.paidAt != null) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'Paid On', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 4.h), Text( _formatDate(payment.paidAt!), style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: Colors.grey.shade800, ), ), ], ), ], ), if (payment.notes != null && payment.notes!.isNotEmpty) ...[ SizedBox(height: 12.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(8.r), ), child: Row( children: [ Icon(Icons.note, size: 16.w, color: Colors.grey.shade600), SizedBox(width: 8.w), Expanded( child: Text( payment.notes!, style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade700, ), ), ), ], ), ), ], ], ), ), ); } Widget _buildDrawCard(MonthlyDraw draw) { final isWinner = draw.winnerId == _authService.currentUser.value?.id; return Card( margin: EdgeInsets.only(bottom: 12.h), elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)), child: Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( gradient: isWinner ? LinearGradient( colors: [Colors.amber.shade50, Colors.amber.shade100], ) : null, borderRadius: BorderRadius.circular(12.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Month ${draw.month}', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: isWinner ? Colors.amber.shade900 : Colors.grey.shade800, ), ), if (isWinner) Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), decoration: BoxDecoration( color: Colors.amber.shade600, borderRadius: BorderRadius.circular(12.r), ), child: Row( children: [ Icon(Icons.emoji_events, color: Colors.white, size: 16.w), SizedBox(width: 4.w), Text( 'Winner!', style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), ], ), SizedBox(height: 16.h), _buildDrawInfo('Prize Amount', '₹${_formatCurrency(draw.prizeAmount)}'), SizedBox(height: 12.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: isWinner ? Colors.amber.shade100 : Colors.grey.shade100, borderRadius: BorderRadius.circular(8.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Winner', style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 4.h), Text( draw.winner?.fullName ?? 'Unknown', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: isWinner ? Colors.amber.shade900 : Colors.grey.shade800, ), ), ], ), ), SizedBox(height: 12.h), Row( children: [ Icon(Icons.event, size: 16.w, color: Colors.grey.shade600), SizedBox(width: 8.w), Text( 'Drawn on ${_formatDate(draw.drawDate)}', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ], ), ), ); } Widget _buildDrawInfo(String label, String value) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12.sp, color: Colors.grey.shade600, ), ), SizedBox(height: 4.h), Text( value, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade800, ), ), ], ); } Widget _buildEmptyPayments() { return Center( child: Padding( padding: EdgeInsets.all(32.w), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.payment_outlined, size: 64.w, color: Colors.grey.shade300, ), SizedBox(height: 16.h), Text( 'No Payments Yet', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade700, ), ), SizedBox(height: 8.h), Text( 'Your payment history will appear here', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ), ); } Widget _buildEmptyDraws() { return Center( child: Padding( padding: EdgeInsets.all(32.w), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.casino_outlined, size: 64.w, color: Colors.grey.shade300, ), SizedBox(height: 16.h), Text( 'No Draws Yet', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: Colors.grey.shade700, ), ), SizedBox(height: 8.h), Text( widget.group.status == 'forming' ? 'Group needs to start before draws can happen' : 'Draw results will appear here', textAlign: TextAlign.center, style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ), ); } Widget _buildStatItem(String label, String value, Color color) { return Column( children: [ Text( value, style: TextStyle( fontSize: 20.sp, fontWeight: FontWeight.bold, color: color, ), ), SizedBox(height: 4.h), Text( label, style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ); } Widget _buildStatusBadge(String status) { Color color; String text; switch (status.toLowerCase()) { case 'active': color = Colors.green.shade600; text = 'Active'; break; case 'forming': color = Colors.orange.shade600; text = 'Forming'; break; case 'completed': color = Colors.blue.shade600; text = 'Completed'; break; default: color = Colors.grey.shade600; text = status; } return Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12.r), border: Border.all(color: color, width: 1.5), ), child: Text( text, style: TextStyle( fontSize: 14.sp, color: color, fontWeight: FontWeight.w600, ), ), ); } Widget _buildPaymentStatusBadge(String status) { Color color; String text; switch (status.toLowerCase()) { case 'success': color = Colors.green.shade600; text = 'Paid'; break; case 'pending': color = Colors.orange.shade600; text = 'Pending'; break; case 'failed': color = Colors.red.shade600; text = 'Failed'; break; case 'cancelled': color = Colors.grey.shade600; text = 'Cancelled'; break; default: color = Colors.grey.shade600; text = status; } return Container( padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8.r), border: Border.all(color: color, width: 1.5), ), child: Text( text, style: TextStyle( fontSize: 12.sp, color: color, fontWeight: FontWeight.w600, ), ), ); } String _formatCurrency(double amount) { final amountStr = amount.toStringAsFixed(0); return amountStr.replaceAllMapped( RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},', ); } String _formatDate(DateTime date) { return '${date.day}/${date.month}/${date.year}'; } }