diff --git a/luckychit/lib/interfaces/manager/add_past_draw_dialog.dart b/luckychit/lib/interfaces/manager/add_past_draw_dialog.dart index 062c748..5c48b1a 100644 --- a/luckychit/lib/interfaces/manager/add_past_draw_dialog.dart +++ b/luckychit/lib/interfaces/manager/add_past_draw_dialog.dart @@ -4,7 +4,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../core/services/chit_group_service.dart'; import '../../core/services/api_service.dart'; import '../../core/models/chit_group.dart'; -import '../../core/models/group_member.dart'; import '../../core/utils/snackbar_util.dart'; class AddPastDrawDialog extends StatefulWidget { @@ -27,7 +26,6 @@ class _AddPastDrawDialogState extends State { final _apiService = ApiService(); String? _selectedMemberId; - String? _selectedMemberName; bool _isLoading = false; int _selectedMonth = 1; int _selectedYear = DateTime.now().year; @@ -105,15 +103,26 @@ class _AddPastDrawDialogState extends State { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.r)), child: Container( width: 500.w, - padding: EdgeInsets.all(24.w), - child: Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header - Row( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.85, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Fixed Header + Container( + padding: EdgeInsets.all(24.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20.r), + topRight: Radius.circular(20.r), + ), + border: Border( + bottom: BorderSide(color: Colors.grey.shade200), + ), + ), + child: Row( children: [ Icon(Icons.history, color: Colors.blue.shade600, size: 28.w), SizedBox(width: 12.w), @@ -132,150 +141,218 @@ class _AddPastDrawDialogState extends State { ), ], ), - SizedBox(height: 24.h), + ), - // Month Info - Container( - padding: EdgeInsets.all(16.w), - decoration: BoxDecoration( - color: Colors.blue.shade50, - borderRadius: BorderRadius.circular(12.r), - border: Border.all(color: Colors.blue.shade200), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Month ${widget.monthNumber}', - style: TextStyle( - fontSize: 18.sp, - fontWeight: FontWeight.bold, - color: Colors.blue.shade800, - ), - ), - Text( - '$_selectedMonth/$_selectedYear', - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.w600, - color: Colors.blue.shade700, - ), - ), - ], - ), - ), - SizedBox(height: 20.h), - - // Select Winner - Text( - 'Who Won This Draw?', - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.w600, - ), - ), - SizedBox(height: 12.h), - Obx(() { - final members = Get.find().groupMembers; - - if (members.isEmpty) { - return Container( - padding: EdgeInsets.all(16.w), - decoration: BoxDecoration( - color: Colors.orange.shade50, - borderRadius: BorderRadius.circular(12.r), - border: Border.all(color: Colors.orange.shade200), - ), - child: Text( - 'Please add members to the group first', - style: TextStyle( - color: Colors.orange.shade900, - fontSize: 14.sp, - ), - ), - ); - } - - return Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey.shade300), - borderRadius: BorderRadius.circular(12.r), - ), + // Scrollable Content + Flexible( + child: SingleChildScrollView( + padding: EdgeInsets.all(24.w), + child: Form( + key: _formKey, child: Column( - children: members.map((member) { - final isSelected = member.id == _selectedMemberId; - return InkWell( - onTap: () { - setState(() { - _selectedMemberId = member.userId; - _selectedMemberName = member.user?.fullName ?? 'Unknown'; - }); - }, - child: Container( - padding: EdgeInsets.all(12.w), - decoration: BoxDecoration( - color: isSelected ? Colors.green.shade50 : null, - border: Border( - bottom: BorderSide(color: Colors.grey.shade200), - ), - ), - child: Row( - children: [ - Icon( - isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, - color: isSelected ? Colors.green.shade600 : Colors.grey.shade400, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Month Info + Container( + padding: EdgeInsets.all(16.w), + decoration: BoxDecoration( + color: Colors.blue.shade50, + borderRadius: BorderRadius.circular(12.r), + border: Border.all(color: Colors.blue.shade200), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Month ${widget.monthNumber}', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.bold, + color: Colors.blue.shade800, ), - SizedBox(width: 12.w), - Expanded( - child: Text( - member.user?.fullName ?? 'Unknown', - style: TextStyle( - fontSize: 16.sp, - fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, + ), + Text( + '$_selectedMonth/$_selectedYear', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: Colors.blue.shade700, + ), + ), + ], + ), + ), + SizedBox(height: 20.h), + + // Select Winner + Text( + 'Who Won This Draw?', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 12.h), + Obx(() { + final members = Get.find().groupMembers; + + if (members.isEmpty) { + return Container( + padding: EdgeInsets.all(16.w), + decoration: BoxDecoration( + color: Colors.orange.shade50, + borderRadius: BorderRadius.circular(12.r), + border: Border.all(color: Colors.orange.shade200), + ), + child: Row( + children: [ + Icon(Icons.warning_amber_rounded, + color: Colors.orange.shade700, size: 20.w), + SizedBox(width: 8.w), + Expanded( + child: Text( + 'Please add members to the group first', + style: TextStyle( + color: Colors.orange.shade900, + fontSize: 14.sp, + ), ), ), - ), - if (isSelected) - Icon(Icons.check_circle, color: Colors.green.shade600), - ], + ], + ), + ); + } + + return Container( + constraints: BoxConstraints( + maxHeight: 300.h, // Limit height for scrolling ), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade300), + borderRadius: BorderRadius.circular(12.r), + ), + child: ListView.builder( + shrinkWrap: true, + itemCount: members.length, + itemBuilder: (context, index) { + final member = members[index]; + final isSelected = member.userId == _selectedMemberId; + final isLast = index == members.length - 1; + + return InkWell( + onTap: () { + setState(() { + _selectedMemberId = member.userId; + }); + }, + borderRadius: BorderRadius.vertical( + top: index == 0 ? Radius.circular(12.r) : Radius.zero, + bottom: isLast ? Radius.circular(12.r) : Radius.zero, + ), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 12.w, + vertical: 14.h, + ), + decoration: BoxDecoration( + color: isSelected ? Colors.green.shade50 : null, + border: !isLast ? Border( + bottom: BorderSide(color: Colors.grey.shade200), + ) : null, + ), + child: Row( + children: [ + Icon( + isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, + color: isSelected ? Colors.green.shade600 : Colors.grey.shade400, + size: 24.w, + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + member.user?.fullName ?? 'Unknown', + style: TextStyle( + fontSize: 16.sp, + fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, + ), + ), + if (member.user?.mobileNumber != null) ...[ + SizedBox(height: 2.h), + Text( + member.user!.mobileNumber, + style: TextStyle( + fontSize: 13.sp, + color: Colors.grey.shade600, + ), + ), + ], + ], + ), + ), + if (isSelected) + Icon(Icons.check_circle, + color: Colors.green.shade600, size: 20.w), + ], + ), + ), + ); + }, + ), + ); + }), + SizedBox(height: 20.h), + + // Prize Amount + Text( + 'Prize Amount', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, ), - ); - }).toList(), + ), + SizedBox(height: 8.h), + TextFormField( + controller: _prizeAmountController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: 'Prize amount won', + prefixText: '₹ ', + prefixIcon: Icon(Icons.currency_rupee), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12.r), + ), + filled: true, + fillColor: Colors.grey.shade50, + ), + validator: (value) { + if (value?.isEmpty ?? true) return 'Required'; + if (double.tryParse(value!) == null) return 'Invalid amount'; + return null; + }, + ), + ], ), - ); - }), - SizedBox(height: 20.h), - - // Prize Amount - Text( - 'Prize Amount', - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.w600, ), ), - SizedBox(height: 8.h), - TextFormField( - controller: _prizeAmountController, - keyboardType: TextInputType.number, - decoration: InputDecoration( - hintText: 'Prize amount won', - prefixText: '₹ ', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12.r)), - filled: true, - fillColor: Colors.grey.shade50, - ), - validator: (value) { - if (value?.isEmpty ?? true) return 'Required'; - if (double.tryParse(value!) == null) return 'Invalid amount'; - return null; - }, - ), - SizedBox(height: 24.h), + ), - // Actions - Row( + // Fixed Footer with Actions + Container( + padding: EdgeInsets.all(24.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20.r), + bottomRight: Radius.circular(20.r), + ), + border: Border( + top: BorderSide(color: Colors.grey.shade200), + ), + ), + child: Row( children: [ Expanded( child: OutlinedButton( @@ -303,6 +380,7 @@ class _AddPastDrawDialogState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), + elevation: 2, ), child: _isLoading ? SizedBox( @@ -321,8 +399,8 @@ class _AddPastDrawDialogState extends State { ), ], ), - ], - ), + ), + ], ), ), ); diff --git a/luckychit/lib/interfaces/manager/group_details_page.dart b/luckychit/lib/interfaces/manager/group_details_page.dart index 356cc32..4aca808 100644 --- a/luckychit/lib/interfaces/manager/group_details_page.dart +++ b/luckychit/lib/interfaces/manager/group_details_page.dart @@ -793,13 +793,55 @@ class _GroupDetailsPageState extends State with SingleTickerPr return const Center(child: CircularProgressIndicator()); } - // Auto-generate sample data if empty + // Show empty state if no data from backend if (financialData.isEmpty) { - WidgetsBinding.instance.addPostFrameCallback((_) { - final sampleData = _service.generateSampleFinancialData(widget.group); - _service.financialData.value = sampleData; - }); - return const Center(child: CircularProgressIndicator()); + return Center( + child: Padding( + padding: EdgeInsets.all(32.w), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.table_chart_outlined, + size: 64.w, + color: Colors.grey.shade400, + ), + SizedBox(height: 16.h), + Text( + 'No Financial Data Available', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: Colors.grey.shade700, + ), + ), + SizedBox(height: 8.h), + Text( + 'Financial data will appear here once\nthe group becomes active', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.sp, + color: Colors.grey.shade600, + ), + ), + SizedBox(height: 24.h), + ElevatedButton.icon( + onPressed: () => _service.loadGroupFinancialData(widget.group.id), + icon: const Icon(Icons.refresh), + label: const Text('Refresh Data'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue.shade600, + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric( + horizontal: 24.w, + vertical: 12.h, + ), + ), + ), + ], + ), + ), + ); } return RefreshIndicator( @@ -2285,7 +2327,27 @@ class _GroupDetailsPageState extends State with SingleTickerPr final nextMonthName = _getMonthName(nextMonth); final nextMonthNumber = currentMonthNumber + 1; - // Note: Bid amounts are now hardcoded to match the image data + // Get current month draw data + final currentDraw = _service.monthlyDraws.firstWhereOrNull( + (draw) => draw.month == currentMonth && draw.year == currentYear, + ); + + // Get financial data for current month + final financialData = _service.financialData; + final currentMonthFinancial = financialData.firstWhereOrNull( + (entry) => entry.monthYear == '$currentMonth/$currentYear', + ); + + // Determine bid/prize amounts - use actual data or fallback to group values + final currentBidAmount = currentMonthFinancial?.bidAmount ?? currentDraw?.prizeAmount ?? group.totalValue; + final currentPrizeAmount = currentDraw?.prizeAmount ?? currentBidAmount; + + // For next month, estimate based on pattern or use group total value + final nextMonthFinancial = financialData.firstWhereOrNull( + (entry) => entry.monthYear == '$nextMonth/$nextYear', + ); + final nextBidAmount = nextMonthFinancial?.bidAmount ?? group.totalValue; + final nextPrizePool = nextMonthFinancial?.bidAmount ?? group.totalValue; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -2355,7 +2417,7 @@ class _GroupDetailsPageState extends State with SingleTickerPr crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - _formatIndianCurrency(190900), // September 2025 bid amount from the image + _formatIndianCurrency(currentBidAmount), style: TextStyle( fontSize: 20.sp, fontWeight: FontWeight.bold, @@ -2415,7 +2477,7 @@ class _GroupDetailsPageState extends State with SingleTickerPr crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - _formatIndianCurrency(190900), // September 2025 prize amount from the image + _formatIndianCurrency(currentPrizeAmount), style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, @@ -2494,7 +2556,7 @@ class _GroupDetailsPageState extends State with SingleTickerPr crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - _formatIndianCurrency(193500), // October 2025 expected bid amount + _formatIndianCurrency(nextBidAmount), style: TextStyle( fontSize: 20.sp, fontWeight: FontWeight.bold, @@ -2554,7 +2616,7 @@ class _GroupDetailsPageState extends State with SingleTickerPr crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - _formatIndianCurrency(193500), // October 2025 prize pool amount + _formatIndianCurrency(nextPrizePool), style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold,